4.3 接收数据包(Packet)

接收端收到 UDP 报文后,解析 data 帧对应的 Session 或者 Stream,使用发送端传过来的序号(packId)创建 Packet 对象,设置为 ACK 状态,设置接收完成时间。把 Payload 数据封装进入 Packet 对象,并放入到 Session 或者 Stream 的接收缓存中。然后通过 Session 或者 Stream 发送 ACK 帧给发送端(采用 Session 或 Stream 需与发送端一致)。

通过 Session 发送 ACK 帧格式

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------------------------------+-------------------------------+
|        [id from client]       |        [id from server]       |
+-------------------------------+-------------------------------+
|                        timestamp ...                          |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                    ... timestamp [curent time]                |
+-+-+-+-----+-+-+-------+-------+-------------------------------+
|S|P|F| RSV |S|F|  RSV  |OPCODE |          Payload len          |
|T|A|R| [0] |L|I|  [0]  |[0x4]  |             [0]               |
|R|C|A|     |O|N|       |       |                               |
|E|K|G|     |W| |       |       |                               |
|0|1|0|     |0|0|       |       |                               |
+-+-+-+-----+-+-+-------+-------+-------------------------------+
|                      Packet Id [packId]                       |
+---------------------------------------------------------------+

timestamp 字段写入当前时间戳,精确到毫秒。STRE 字段设置为 0,PACK 字段设置为 1,FRAG、SLOW、FIN 设置为 0。RSV 字段设置为 0。OPCODE 字段设置为 0x4,Payload len 字段设置为 0。Packet Id 字段写入数据包序号(packId)。

通过 Stream 发送 ACK 帧格式

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------------------------------+-------------------------------+
|        [id from client]       |        [id from server]       |
+-------------------------------+-------------------------------+
|                        timestamp ...                          |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                    ... timestamp [curent time]                |
+-+-+-+-----+-+-+-------+-------+-------------------------------+
|S|P|F| RSV |S|F|  RSV  |OPCODE |          Payload len          |
|T|A|R| [0] |L|I|  [0]  |[0x4]  |             [0]               |
|R|C|A|     |O|N|       |       |                               |
|E|K|G|     |W| |       |       |                               |
|1|1|0|     |0|0|       |       |                               |
+-+-+-+-----+-+-+-------+-------+-------------------------------+
|              Stream Id [random id from client]                |
+---------------------------------------------------------------+
|                      Packet Id [packId]                       |
+---------------------------------------------------------------+

timestamp 字段写入当前时间戳,精确到毫秒。STRE 字段设置为 1,PACK 字段设置为 1,FRAG、SLOW、FIN 设置为 0。RSV 字段设置为 0。OPCODE 字段设置为 0x4,Payload len 字段设置为 0。Stream Id 字段写入当前流 ID,Packet Id 字段写入数据包序号(packId)。

发送端收到 ACK 帧后,根据解析出的数据包序号(packId),从 Session 或者 Stream 的发送缓存中取出对应的 Packet,并更新为 ACK 状态。

如果通信正常,没有丢包发生,此时发送端与接收端缓存中的 Packet 都已经是 ACK 状态。即接收端已接收完成,且发送端已确认接收端接收完成。