UDT源码剖析(七)之Packet

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()`

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;
}
```

猜你喜欢

转载自www.cnblogs.com/ukernel/p/9191059.html