任何协议不管是网络协议还是文件协议(mp4,avi等)基本都市 由 包头+包体 格式组成
UDT包头+包体
#include "packet.h" packet.cpp
//
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Packet Header |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// ~ Data / Control Information Field ~
// | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
具体包头 有2中类型的包头,一种是针对上层用户的数据包头,另一种是针对UDT内部的控制包头
数据包头:
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |0| Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |ff |o| Message Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Time Stamp |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Destination Socket ID |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// bit 0:
// 0: Data Packet
// 1: Control Packet
// bit ff:
// 11: solo message packet
// 10: first packet of a message
// 01: last packet of a message
// bit o:
// 0: in order delivery not required
// 1: in order delivery required
控制包头:
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |1| Type | Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Additional Info |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Time Stamp |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Destination Socket ID |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// bit 1-15:
// 0: Protocol Connection Handshake
// Add. Info: Undefined
// Control Info: Handshake information (see CHandShake)
// 1: Keep-alive
// Add. Info: Undefined
// Control Info: None
// 2: Acknowledgement (ACK)
// Add. Info: The ACK sequence number
// Control Info: The sequence number to which (but not include) all the previous packets have beed received
// Optional: RTT
// RTT Variance
// available receiver buffer size (in bytes)
// advertised flow window size (number of packets)
// estimated bandwidth (number of packets per second)
// 3: Negative Acknowledgement (NAK)
// Add. Info: Undefined
// Control Info: Loss list (see loss list coding below)
// 4: Congestion/Delay Warning
// Add. Info: Undefined
// Control Info: None
// 5: Shutdown
// Add. Info: Undefined
// Control Info: None
// 6: Acknowledgement of Acknowledement (ACK-square)
// Add. Info: The ACK sequence number
// Control Info: None
// 7: Message Drop Request
// Add. Info: Message ID
// Control Info: first sequence number of the message
// last seqeunce number of the message
// 8: Error Signal from the Peer Side
// Add. Info: Error code
// Control Info: None
// 0x7FFF: Explained by bits 16 - 31
//
// bit 16 - 31:
// This space is used for future expansion or user defined control packets.
控制包头的包体 根据包头 类型 来决定。
具体打包函数如下:
void CPacket::pack(int pkttype, void* lparam, void* rparam, int size)
{
// Set (bit-0 = 1) and (bit-1~15 = type)
m_nHeader[0] = 0x80000000 | (pkttype << 16);
// Set additional information and control information field
switch (pkttype)
{
case 2: //0010 - Acknowledgement (ACK)
// ACK packet seq. no.
if (NULL != lparam)
m_nHeader[1] = *(int32_t *)lparam;
// data ACK seq. no.
// optional: RTT (microsends), RTT variance (microseconds) advertised flow window size (packets), and estimated link capacity (packets per second)
m_PacketVector[1].iov_base = (char *)rparam;
m_PacketVector[1].iov_len = size;
break;
case 6: //0110 - Acknowledgement of Acknowledgement (ACK-2)
// ACK packet seq. no.
m_nHeader[1] = *(int32_t *)lparam;
// control info field should be none
// but "writev" does not allow this
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
m_PacketVector[1].iov_len = 4; //0;
break;
case 3: //0011 - Loss Report (NAK)
// loss list
m_PacketVector[1].iov_base = (char *)rparam;
m_PacketVector[1].iov_len = size;
break;
case 4: //0100 - Congestion Warning
// control info field should be none
// but "writev" does not allow this
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
m_PacketVector[1].iov_len = 4; //0;
break;
case 1: //0001 - Keep-alive
// control info field should be none
// but "writev" does not allow this
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
m_PacketVector[1].iov_len = 4; //0;
break;
case 0: //0000 - Handshake
// control info filed is handshake info
m_PacketVector[1].iov_base = (char *)rparam;
m_PacketVector[1].iov_len = size; //sizeof(CHandShake);
break;
case 5: //0101 - Shutdown
// control info field should be none
// but "writev" does not allow this
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
m_PacketVector[1].iov_len = 4; //0;
break;
case 7: //0111 - Message Drop Request
// msg id
m_nHeader[1] = *(int32_t *)lparam;
//first seq no, last seq no
m_PacketVector[1].iov_base = (char *)rparam;
m_PacketVector[1].iov_len = size;
break;
case 8: //1000 - Error Signal from the Peer Side
// Error type
m_nHeader[1] = *(int32_t *)lparam;
// control info field should be none
// but "writev" does not allow this
m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
m_PacketVector[1].iov_len = 4; //0;
break;
case 32767: //0x7FFF - Reserved for user defined control packets
// for extended control packet
// "lparam" contains the extended type information for bit 16 - 31
// "rparam" is the control information
m_nHeader[0] |= *(int32_t *)lparam;
if (NULL != rparam)
{
m_PacketVector[1].iov_base = (char *)rparam;
m_PacketVector[1].iov_len = size;
}
else
{
m_PacketVector[1].iov_base = (char *)&__pad;
m_PacketVector[1].iov_len = 4;
}
break;
default:
break;
}
}
握手报文 也就是控制报文类型为 0 的报文,其对于的包体为CHandShake 类型
const int CHandShake::m_iContentSize = 48;
握手报文的封包和拆包
int CHandShake::serialize(char* buf, int& size)
{
if (size < m_iContentSize)
return -1;
int32_t* p = (int32_t*)buf;
*p++ = m_iVersion;
*p++ = m_iType;
*p++ = m_iISN;
*p++ = m_iMSS;
*p++ = m_iFlightFlagSize;
*p++ = m_iReqType;
*p++ = m_iID;
*p++ = m_iCookie;
for (int i = 0; i < 4; ++ i)
*p++ = m_piPeerIP[i];
size = m_iContentSize;
return 0;
}
int CHandShake::deserialize(const char* buf, int size)
{
if (size < m_iContentSize)
return -1;
int32_t* p = (int32_t*)buf;
m_iVersion = *p++;
m_iType = *p++;
m_iISN = *p++;
m_iMSS = *p++;
m_iFlightFlagSize = *p++;
m_iReqType = *p++;
m_iID = *p++;
m_iCookie = *p++;
for (int i = 0; i < 4; ++ i)
m_piPeerIP[i] = *p++;
return 0;
}