CPacket
class CPacket
{
public:
int32_t& m_iSeqNo; // 序列号
int32_t& m_iMsgNo; // 信息号
int32_t& m_iTimeStamp; // 更新RTT的Timestamp
int32_t& m_iID; // 目的地Socket ID
char*& m_pcData; // 数据
static const int m_iPktHdrSize; // 头部信息(16字节)
protected: //真正的数据信息
uint32_t m_nHeader[4]; // 16字节的UDT头部
iovec m_PacketVector[2]; // UDT头部数据和真实的数据信息
int32_t __pad;
};
class CHandShake
{
public:
static const int m_iContentSize; //握手包除了头部信息,有额外的48个字节
public:
int32_t m_iVersion; // UDT version
int32_t m_iType; // UDT socket type
int32_t m_iISN; // random initial sequence number
int32_t m_iMSS; // maximum segment size
int32_t m_iFlightFlagSize; // flow control window size
int32_t m_iReqType; // connection request type: 1: regular connection request, 0: rendezvous connection request, -1/-2: response
int32_t m_iID; // socket ID
int32_t m_iCookie; // cookie
uint32_t m_piPeerIP[4]; // The IP address that the peer's UDP port is bound to
};
CPacket::CPacket():
m_iSeqNo((int32_t&)(m_nHeader[0])), //将引用指向头部信息
m_iMsgNo((int32_t&)(m_nHeader[1])),
m_iTimeStamp((int32_t&)(m_nHeader[2])),
m_iID((int32_t&)(m_nHeader[3])),
m_pcData((char*&)(m_PacketVector[1].iov_base)),
__pad()
{
for (int i = 0; i < 4; ++ i) //将头部的信息初始化为0
m_nHeader[i] = 0;
m_PacketVector[0].iov_base = (char *)m_nHeader; //初始化真实发送的数据结构
m_PacketVector[0].iov_len = CPacket::m_iPktHdrSize;
m_PacketVector[1].iov_base = NULL;
m_PacketVector[1].iov_len = 0;
}
- 获取与设置数据长度:
void CPacket::setLength(int len)
和int CPacket::getLength() const
int CPacket::getLength() const
{
return m_PacketVector[1].iov_len;
}
void CPacket::setLength(int len)
{
m_PacketVector[1].iov_len = len;
}
- 打包一个控制包:
void CPacket::pack(int pkttype, void* lparam, void* rparam, int size)
void CPacket::pack(int pkttype, void* lparam, void* rparam, int size)
{
// Set (bit-0 = 1) and (bit-1~15 = type)
// 很明显是打包control packet
m_nHeader[0] = 0x80000000 | (pkttype << 16);
//根据提供的信息打包不同类型的控制包,不同控制包的头部信息是不同的,需要填充不同的数据
switch (pkttype)
{
case 2: //0010 - Acknowledgement (ACK)
if (NULL != lparam) //如果时ACK,设置bit32~bit63为ACK序列号
m_nHeader[1] = *(int32_t *)lparam;
m_PacketVector[1].iov_base = (char *)rparam; //设置ACK包中的数据选项
m_PacketVector[1].iov_len = size;
break;
case 6: //0110 - Acknowledgement of Acknowledgement (ACK-2)
m_nHeader[1] = *(int32_t *)lparam; //在bit32~bit63填充ACK序列号
//应答ACK包,除了报头没有额外的信息,但是需要填充
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; //在数据区域填充丢失的list信息
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; //拥塞警告;
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; //生存报文
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; //握手报文,在数据区域填充CHandShake
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; //连接终止报文
m_PacketVector[1].iov_len = 4; //0;
break;
case 7: //0111 - Message Drop Request
// msg id
m_nHeader[1] = *(int32_t *)lparam; //消息丢弃请求.需要丢弃的消息ID
//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;
}
}
- 获取包中的信息:
int CPacket::getFlag() const
和int CPacket::getType() const
和int CPacket::getExtendedType() const
和int32_t CPacket::getAckSeqNo() const
和int CPacket::getMsgBoundary() const
和bool CPacket::getMsgOrderFlag() const
和int32_t CPacket::getMsgSeq() const
int CPacket::getFlag() const //控制包返回1,数据包返回1
{
// read bit 0
return m_nHeader[0] >> 31;
}
int CPacket::getType() const //获取控制包的具体类型:ACK,ACK-2,HandShake等
{
// read bit 1~15
return (m_nHeader[0] >> 16) & 0x00007FFF;
}
int CPacket::getExtendedType() const //获取保留给用户实现的自定义类型
{
// read bit 16~31
return m_nHeader[0] & 0x0000FFFF;
}
int32_t CPacket::getAckSeqNo() const //获取ACK序列号
{
// read additional information field
return m_nHeader[1];
}
int CPacket::getMsgBoundary() const //判断数据流的位置,起始包,终止包或者独立包
{
// read [1] bit 0~1
return m_nHeader[1] >> 30;
}
bool CPacket::getMsgOrderFlag() const //判断数据包是否需要立即提交给用户
{
// read [1] bit 2
return (1 == ((m_nHeader[1] >> 29) & 1));
}
int32_t CPacket::getMsgSeq() const //获取MSG的编号
{
// read [1] bit 3~31
return m_nHeader[1] & 0x1FFFFFFF;
}
CHandShake
- 获取握手包信息:
int CHandShake::serialize(char* buf, int& size)
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)
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;
}