UDP基础-1

基于UDP的通信过程:

客户端和服务端区分不明显!即不做区分!
基本流程是:

  • socket创建套接字
  • 仅绑定端口号(绑定端口是可选项)
  • 发送数据或者接收数据
  • 关闭socket服务
  1. UDP数据包格式:

image



image

  • 四类报文的数据格式:
  1. 读写请求:
操作码 文件名 0 模式 0
2Bytes 若干Bytes 1B 若干字节 1B
  1. 数据包:
操作码 块编号 数据
2B 2B 512B
  1. ACK:
操作码 块编号
2B 2B
  1. ERROR:
操作码 差错码 差错信息 0
2B 2B 若干字节 1B
  • 操作码的取值及其含义:
  • 等于1:表示下载请求
  • 等于2:上传请求
  • 等于3:表示本次报文为数据包
  • 等于4:表示本次报文为ACK信息
  • 等于5:本次报文为出错信息

2. 常用struct符号含义:

  • 表一
符号 对应C语言类型 数据大小
H unsigned short 2个字节
b signed char 1个字节
s char 一个字节
  • 表二
特殊符号 含义
大端格式(默认)

3. 常用符号图示:

image




image

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字节
type 操作码 文件名 0 模式 0
内容 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,第二个字段必然是块编号,其值根据程序来判断)

两件事:

  1. 如果当前数据包的数据部分小于512字节,那么可以给服务器发ACK,表示文件已经传完,可以关闭ftcp连接了。
  2. 每当客户端接收了一个数据包,就要给服务端返回一个ACK确认。
posted @ 2018-03-20 14:01  hzhang_NJU  阅读(271)  评论(0编辑  收藏  举报