网络编程——协议基础( 二 )


udpSocket = None
destIp = ""
destPort = 0
 
def main():
 
global udpSocket
global destIp
global destPort
 
destIp = input("对方的ip:")
destPort = int(input("对方的ip:"))
 
udpSocket = socket(AF_INET, SOCK_DGRAM)
udpSocket.bind(("", 4567))
 
tr = Thread(target=recvData)
ts = Thread(target=sendData)
 
tr.start() #启动接收数据线程
ts.start() #启动发送数据线程
 
tr.join() #等待两个线程结束
ts.join()
 
if __name__ == "__main__":
main()
八、wireshark抓包工具的使用
wireshark工具可以抓取当前电脑中所有网络数据,具体如图所示:

网络编程——协议基础

文章插图
 
九、tftp下载器的使用(tftpd64或tftpd32)
tftp是tcp/ip协议族中用来将客户端和服务器之间进行简单文件传输的协议 。
特点如下:
基于UDP实现,可能会丢包,实现过程为收到-回复,下载过程如下:
网络编程——协议基础

文章插图
 
TFTP数据表格式如下:
读写请求格式:操作码为1或2,分别表示读或写;文件名为文件名称;0为固定写法;模式有几种,最常用的为octet;最后跟一个0 。
数据表格式:操作码固定为3;文件名为文件名称;块编号为文件分割的块编号;数据为详细数据 。
确认格式:操作码固定为4;块编号为确认收到的文件分块编号 。
错误表格式:操作码固定为5;差错码为固定好的错误编号;后面接具体差错信息;最后跟一个0;
注意:确认包发往的是服务器发送本地进程时分配的随机端口!
怎样确定数据已经发送完毕了?
规定,当客户端接收到的数据?于516(2字节操作码+2个字节的序号+512字节数据) 时,就意味着服务器发送完毕了 。
怎样保证包中每个码的字节数?
python中组包代码如下:
网络编程——协议基础

文章插图
 
!:表示网络中的数据,网络中的数据用大端表示 。
H:占用2个字节,对应后面的1 。
8s:占用8个字节,对应后面的"test.jpg" 。
b:占用1个字节,对应后面的0 。
5s:占用5个字节,对应后面的"octet" 。
b:占用1个字节,对应后面的0 。
表格式如图所示:
网络编程——协议基础

文章插图
 
使用python从tftp服务器中下载文件
1)首先启动tftpd64应用程序,设置好下载的目录和ip地址 。
2)python代码如下:
# -*- coding:utf-8 -*-
 
import struct
from socket import *
import time
import os
 
def main():
 
#0. 获取要下载的文件名字:
downloadFileName = raw_input("请输入要下载的文件名:")
 
#1.创建socket
udpSocket = socket(AF_INET, SOCK_DGRAM)
 
requestFileData = https://www.isolves.com/it/cxkf/bk/2020-07-09/struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0)
 
#2. 发送下载文件的请求
udpSocket.sendto(requestFileData, ("192.168.119.215", 69))
 
flag = True #表示能够下载数据,即不擅长,如果是false那么就删除
num = 0
f = open(downloadFileName, "w")
 
while True:
#3. 接收服务发送回来的应答数据
responseData = https://www.isolves.com/it/cxkf/bk/2020-07-09/udpSocket.recvfrom(1024)
 
# print(responseData)
recvData, serverInfo = responseData
 
opNum = struct.unpack("!H", recvData[:2])
 
packetNum = struct.unpack("!H", recvData[2:4])
 
print(packetNum[0])
 
# print("opNum=%d"%opNum)
# print(opNum)
 
# if 如果服务器发送过来的是文件的内容的话:
if opNum[0] == 3: #因为opNum此时是一个元组(3,),所以需要使用下标来提取某个数据
 
#计算出这次应该接收到的文件的序号值,应该是上一次接收到的值的基础上+1
num = num + 1
 
# 如果一个下载的文件特别大,即接收到的数据包编号超过了2个字节的大小
# 那么会从0继续开始,所以这里需要判断,如果超过了65535 那么就改为0


推荐阅读