java udp分包重组算法_UDP分包重组算法 1

//Packet.h

#include "InetAddr.h" //对socket地址操作封装的类,比如char*IP转成ULONG

#include

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

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值