- 加入time以标识数据包发送的时间(26)
- CCP更名CFUP(25)
- 限制可靠传输时数据包长度与窗口大小, 优化某些细节字眼(24)
- CSCP更名CCP(23)
- 解除对IPv4和IPv6的限制(22)
- 规定协议只能使用小端序(21)
- CSCP重构(20)
- 本协议基于UDP, 面向连接协议, 无流量控制可靠传输应用层协议
- 本协议只关心数据包可靠传输, 对于数据内容请自行定义
- 本协议需要自行实现应用层协议管理器和协议对象, 关于实现说明均在下文可查看
字节 | 0 | 1 | 2 | 3 ~ 10 | 11 | 12 | 13 | ... |
S0 | cf | SID | time | |||||
S1 | cf | SID | time | AID | ||||
S2 | cf | SID | time | data | ... |
字节 | 0 | 1 | 2 | 3 | ... |
S3 | cf | AID | |||
S4 | cf | data | ... |
名称 | 含义 | 数据类型 |
---|---|---|
cf | 命令和属性 | byte |
SID | 本包ID | ushort(uint16) |
time | 时间戳 | long(int64) |
AID | 应答包ID | ushort(uint16) |
data | 用户数据 | byte[] |
- cf命令和属性: 表示当前发送包的命令和属性
- SID本包ID: 表示当前自己发包的ID号, 为了避免乱包以及方便丢包重发
- 当cmd的NA位为true时, 本包ID可忽略
- 当包ID大于65535时从0开始
- AID应答包ID: 表示应答对方的包ID号, 当cmd为ACK时, 需要应答包ID号
- time表示该数据包发送的时间
- data用户数据: 表示该包中的用户数据
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
名称 | flags | cmd | ||||||
含义 | 属性 | 命令 |
位 | 名称 | 含义 |
---|---|---|
7 | UDL | 链表包 |
6 | UD | 用户数据 |
5 | NA | 无需应答 |
4 | RT | 重发包 |
3 |
bin | hex | 名称 | 含义 |
---|---|---|---|
000 | 0 | NULL | 无命令 |
001 | 1 | RC | 请求通信 |
010 | 2 | ACK | 应答 |
011 | 3 | RC ACK | 请求应答 |
100 | 4 | C | 结束通信 |
101 | 5 | H | 心跳包 |
110 | 6 | ||
111 | 7 |
- 本协议所有整形数据均使用小端序进行dump
- 请求通信可以由任意端发起, 必须伴随3次握手过程, 否则视为无效数据
- 结束通信只需要发送C NA数据包即可, 若不是C NA, 视为无效数据
- 如果是是无需应答的包, 不能有本包ID(SID)
- 应答包需要包含应答包ID, 应答包ID(AID)值为对方发的需要确认的ID
- 纯ACK命令(应答包)无需应答, NA必须为true, 否则数据包无效
- 心跳包, 请求通信, 必须应答, NA必须为false, 否则数据包无效
- 心跳包不能包含用户数据, UD位和用户数据会被忽略
- 如果UD位为false(不包含用户数据), UDL位会被忽略
- 包含命令的数据包不能是链表包, UDL位会被忽略
- RT与NA为互斥位, 只能允许其中一个为true, 否则视为无效数据
- 当NA位为false时, 数据传输为可靠传输
- 当UDL位为true时, 表示接下来连续的几个用户数据包为连续数据, 此时不会立即触发readyRead, 而是等待最后一个用户数据包的UDL位为false时表示连续包结束. 在本次传输中所有数据包加起来的数据大小总量叫做传输数据量
- 用户数据长度最大不超过
1005Byte
, 若超过1005Byte
, 将会把数据包拆成若干个链表包(1005Byte
为自定数据块大小, 最大不能超过65516Byte) - 将用户单个数据包最大长度定义为m(参考上一条规则), 发送窗口大小最大为
64
个, 也就是一瞬间最多允许发送64
* m数据. 若发送的数据包超过64
个, 多出来的数据包将队列到发送缓存, 当窗口内有连续性被应答的数据包, 窗口立即向后滑动(64
为自定发送窗口大小, 最大不能超过65533) - 如果对方应答超时后重发数据包, RT必须为true, 否则可能会造成接收方误判
- 接收方需要记录接收到对方SID的最后接收的时间time, 以免出现这种情况: 我先接收到RT数据包, 然后接收到原数据包, 导致通信错误. 如果先接收到RT包, 那么RT包的time一定比原包大, 那么原包被丢弃, 不做处理
- 当NA位为true时, 表示立即发送的数据无需应答, 此时可以不保证可靠传输, 无需经过窗口
- 在连接过程或者通信过程中, 如果任意一端出现不可修复的特殊情况或错误, 可以发送C NA UD data数据包来立即终止本次通信, data的内容为错误信息
- 普通数据传输可代替心跳包. 心跳包的作用只是在连接空闲时检测对方在线状态, 如果普通数据传输正常, 说明对方在线状态正常, 此时无需发送心跳
sequenceDiagram
participant P1
participant P2
Note over P1, P2: 开始
P1 ->> P2: RC SID=0
activate P2
Note left of P1: OID = -1 ID = 0
Note right of P2: ID = 0 OID = 0
P2 ->> P1: RC ACK SID=0 AID=0
deactivate P2
activate P1
Note left of P1: OID = 0 ID = 1
P1 ->> P2: NA ACK AID=0
deactivate P1
Note right of P2: ID = 1 OID = 0
Note over P1, P2: OID=0 ID=1 完成连接 ID=1 OID=0
sequenceDiagram
participant P1
participant P2
Note over P1, P2:OID=y-1 ID=x 开始 ID=y OID=x-1
P1 ->> P2: UD SID=x data
activate P2
Note left of P1: OID = y-1 ID = x
Note right of P2: ID = y OID = x
P2 ->> P1: NA ACK AID=x
deactivate P2
Note left of P1: OID = y-1 ID = x+1
Note over P1, P2: OID=y-1 ID=x+1 完成传输 ID=y OID=x
sequenceDiagram
participant P1
participant P2
Note over P1, P2:OID=y-1 ID=x 开始 ID=y OID=x-1
P1 ->> P2: C NA data
Note over P1, P2: 断开连接
- 如果有重复连接同一个主机的情况, 管理器可以直接检索连接列表里已连接的对象, 并直接触发连接成功, 返回该对象
- 本协议不允许使用域名, 只能使用IP地址连接
若迫不得已使用域名, 请自行实现域名解析与多条目检索等功能 - 65516Byte的由来
UDP头部8个字节, UDP数据包最长65535
CFUP头部包含data最长的情况为S4, 头部占11个字节
65535 - 8 - 11 = 65516
另外这不是一个固定值, 需要根据你的实现来确定