本文共 1486 字,大约阅读时间需要 4 分钟。
基于UDP的通信过程:
客户端和服务端区分不明显!即不做区分!
基本流程是: - socket创建套接字
- 仅绑定端口号(绑定端口是可选项)
- 发送数据或者接收数据
- 关闭socket服务
- UDP数据包格式:
- 读写请求:
2Bytes | 若干Bytes | 1B | 若干字节 | 1B |
- 数据包:
- ACK:
- ERROR:
操作码的取值及其含义:
- 等于1:表示下载请求
- 等于2:上传请求
- 等于3:表示本次报文为数据包
- 等于4:表示本次报文为ACK信息
- 等于5:本次报文为出错信息
2. 常用struct符号含义:
H | unsigned short | 2个字节 |
b | signed char | 1个字节 |
s | char | 一个字节 |
3. 常用符号图示:
4. struct模块:
- 实现对数据的封装与拆分,把若干数据封装成一个符合5类报文格式要求的类结构体
- 常用函数:pack, unpack, cmdTuple
- pack(fmt, v1, v2, ...) #按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流)
- unpack(fmt, string) #按照给定的格式(fmt)解析字节流string,返回解析出来的tuple
- calcsize(fmt)
计算给定的格式(fmt)占用多少字节的内存
实例:
struct.pack(“!H8sb5sb”,1,“test.jpg”,0,“octet”,0) struct.pack("!HH",4,p_num) cmdTuple = struct.unpack("!HH", recvData[:4])
- 第一行:表示一个下载请求,文件名是test.jpg,模式是octet 5个字段的大小分别为:H即为2字节,8s即为8字节,b即为1字节,5s即为5字节,b即1字节。即:操作码字段内容为1大小为2字节,文件名字段内容为test.jpg大小为8字节,0字段内容为0大小为1字节,模式字段内容为octet大小为5字节,0字段内容为0大小为1字节 {可以把这个解读画成表格}
内容 | 1(下载请求) | test.jpg | 0 | octet | 0 |
大小 | 2字节 | 8字节 | 1字节 | 5字节 | 0字节 |
然后将之封装成一个字符流,即可发送到网络。
- 第二行:大端模式,是一个ACK信息。操作码字段的内容为4即标识本报文为ACK,块编号字段的内容为
p_num
,操作码字段的大小为2字节,块编号字段的大小也为2字节。
之后就可以pack,。
- 第三行:大端模式,有两个字段,分别为2字节,根据这个来解包。把得到的两个字段拼接成一个tuple返回给
cmdTuple
。后面再根据ACK的格式分析字段的内容与大小是否正确,进一步判断本报文是否为ACK信息或者错误包。(比如:如果是ACK信息,那么这两个字段第一个字段必然是操作码且内容为4,第二个字段必然是块编号,其值根据程序来判断)
两件事:
- 如果当前数据包的数据部分小于512字节,那么可以给服务器发ACK,表示文件已经传完,可以关闭ftcp连接了。
- 每当客户端接收了一个数据包,就要给服务端返回一个ACK确认。
转载于:https://www.cnblogs.com/LS1314/p/8608909.html