zoukankan      html  css  js  c++  java
  • 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() constint CPacket::getType() constint CPacket::getExtendedType() constint32_t CPacket::getAckSeqNo() const int CPacket::getMsgBoundary() constbool CPacket::getMsgOrderFlag() constint32_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;
    }
    
  • 相关阅读:
    Java自学-数字与字符串 字符串
    Java自学-数字与字符串 格式化输出
    Java自学-数字与字符串 数学方法
    Java自学-数字与字符串 字符串转换
    Java自学-数字与字符串 装箱和拆箱
    Java自学-接口与继承 UML图
    Mysql优化系列之查询优化干货1
    Mysql优化系列之查询性能优化前篇3(必须知道的几个事实)
    Mysql优化系列之查询性能优化前篇2
    第二十二篇:Spring简单定时任务
  • 原文地址:https://www.cnblogs.com/ukernel/p/9191059.html
Copyright © 2011-2022 走看看