现在的位置: 首页 > 综合 > 正文

UDP分包重组算法 1

2018年02月08日 ⁄ 综合 ⁄ 共 3546字 ⁄ 字号 评论关闭

//Packet.h

#include "InetAddr.h" //对socket地址操作封装的类,比如char*IP转成ULONG
#include <vector>
using namespace std;

//先定义包头

typedef struct _HeadExt
{
    //每帧所有分片公用信息
    char   flag[5];                           //可以任意字符或数字或其他方法,用来标志我们发送的数据
    UINT   m_nSeqNumber;           //本帧序数
    USHORT m_nTotalFragment;   //本帧数据可分成的总片数
    USHORT m_nTotalSize;           //本帧数据总长度
    //每片各自信息
    USHORT m_nFragmentIndex; //每帧分片序数,0 1 2 ... ,/
    USHORT m_usPayloadSize;    //本片数据长度
    USHORT m_usFragOffset;       //本片数据相对总数据的偏移量
    USHORT m_bLastFragment;   //是否最后一帧

    //上 述数据有些重复,可以精简,有时间再修改
 }HeadExt;

 

//从socket接收到的数据
class  PacketIn
{
public :
    PacketIn(char* lpszBuffer=NULL, UINT usBufferSize=0, UINT nDataSize=0);
    virtual ~PacketIn();
    HeadExt head;
    BYTE*    m_lpszBuffer;
    ULONG   ip;
    UINT    port;
    CVLInetAddr addr;
    BOOL Normalize();
    UINT   m_nDataLen;
    UINT   m_usBufferSize;

};

//接收到数据后开始重组使用的一个中间缓冲区,多个PacketIn合成一个Packet
//发送时从一个Packet分割出多片,不过本程序里直接发送,没有封成Packet
class Packet 
{

public:
    enum { TIMEOUT_LOCKFRAGMENTS = 1000 };

     Packet( );
 
    ~Packet();

    void reset();

    void Set(const CVLInetAddr& iaFrom, UINT nSeqNumber );

    BOOL InsertFragment(PacketIn* const pFragment);

    bool m_bUsed;
    int recvedpacks;
    int recvedbytes;
    int seqnum;

    BYTE* m_pBuffer;

//测试用程序,直接访问了类的变量,没有封装成函数。上述变量正常应该写成 SetXXX ,GetXXX   
private:
       BOOL IsFragComplete() const;
   
    ULONG     m_ip;

    USHORT   m_port;
    UINT        m_nSeqNumber;
    vector<int> SeqNumberList;
};

//Packet.cpp

#include "Packet.h"

PacketIn::PacketIn(char* lpszBuffer/*=NULL*/, UINT usBufferSize/*=0*/, UINT nDataSize/*=0*/)
{

    m_lpszBuffer   = (BYTE*)lpszBuffer;
    m_usBufferSize = usBufferSize; //数据最大长度,其实没什么用,已经设置了这个值最大为64000
    m_nDataLen = nDataSize;
}
PacketIn::~PacketIn()
{
}
BOOL PacketIn::Normalize()  //判断收到的数据是否有效
{
    const USHORT usHeaderSize = sizeof(HeadExt);
    if ( !m_lpszBuffer || m_usBufferSize < usHeaderSize )//没什么用
    {
        return FALSE;
    }

    HeadExt* pHeader = (HeadExt*)( m_lpszBuffer  );
    if ( pHeader->m_usPayloadSize != m_nDataLen - usHeaderSize )
    {
        return FALSE;
    }

    head = *pHeader;
    if ( pHeader->m_usPayloadSize > 0 )
    {
        memmove( m_lpszBuffer, m_lpszBuffer + usHeaderSize, pHeader->m_usPayloadSize );
    }
   
    return TRUE;
}

/////////////

//这里是重组数据的临时缓冲,只看这里必然迷惑,先看socket收数据那里,再回来查看
void Packet::Set( const CVLInetAddr& iaFrom, UINT nSeqNumber )
{
    m_iaFrom =  iaFrom;
    m_nSeqNumber = nSeqNumber;
    if(m_pBuffer)
        delete []m_pBuffer;

}

void Packet::reset()
{
    m_bUsed = false;
    recvedpacks = 0;
    seqnum = 0;
    recvedbytes = 0;
    m_pBuffer = NULL;
    m_pBuffer = new BYTE[64000];
    SeqNumberList.clear();
}
Packet::Packet()
{
    //calculate the ttl
    //m_nTTL = RUDP_REASSEMBLE_TIMEOUT*CRudpPeer::PR_SLOWHZ;
    reset();
}

Packet::~Packet()
{
    if(m_pBuffer)
        delete []m_pBuffer;
}

BOOL Packet::InsertFragment(PacketIn* const pFragment)
{

    int nSize = SeqNumberList.size();
    for(int i = 0; i< nSize ;i ++)
    {
        if(nSize ==SeqNumberList[i] )//收到重复数据包
        {
            return FALSE;
        }
    }
    SeqNumberList.push_back(pFragment->head.m_nFragmentIndex);

    memcpy( m_pBuffer + pFragment->head.m_usFragOffset, pFragment->m_lpszBuffer, pFragment->head.m_usPayloadSize);
    recvedbytes += pFragment->head.m_usPayloadSize;
    recvedpacks++;
    m_bUsed = true;

    CString str;
        str.Format("收到数据:m_nSeqNumber%d ,m_nTotalFragment %d,m_nFragmentIndex %d,m_usFragOffset %d,m_nTotalSize %d,recvedbytes %d/r/n",
            pFragment->head.m_nSeqNumber,pFragment->head.m_nTotalFragment,pFragment->head.m_nFragmentIndex,pFragment->head.m_usFragOffset,pFragment->head.m_nTotalSize,pFragment->head.m_usPayloadSize);
        OutputDebugString(str);

    if(recvedbytes == pFragment->head.m_nTotalSize )
        return TRUE;
   
    return FALSE;
}

 

更多技术文章请参见我的个人网站:http://www.joyvc.cn

抱歉!评论已关闭.