分享一个自己写的udp分包组包的例子,一个包以32768为单位分包,每个包有序号,如果乱序或者是缺少,直接舍弃。(有点浪费资源)如果是要实现一个资源发送过程中乱序的重组,请自己修改吧,什么冒泡排序之类的。我就懒得写了。
声明:
typedef struct UDPData
{
unsigned int index; //包序号
unsigned int part; //块总数
unsigned int npart; //当前块序号
unsigned int len; //当前包数据字节数
char data[32768]; //数据 32K
}UDPData;
class UDPSessions
{
public :
UDPSessions(SOCKET h);
UDPSessions();
UDPSessions(SOCKET h , char * i , int p);
int UDPSend(char * data , int len);
int UDPRecv(char *& data);
SOCKET hSocket;
char ipaddr[32];
int port;
private:
int index;
};
定义:
#include "UDPSocket.h"
UDPSessions::UDPSessions(SOCKET h)
{
hSocket = h;
index = -1;
port=0;
}
UDPSessions::UDPSessions(SOCKET h , char * i , int p)
{
hSocket = h;
index = 0;
strcpy(ipaddr , i);
port=p;
}
UDPSessions::UDPSessions()
{
hSocket = NULL;
index = -1;
}
int UDPSessions::UDPSend(char * data , int len)
{
int retlen = 0;
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.S_un.S_addr = INADDR_ANY;
sin.sin_addr.S_un.S_addr = inet_addr(ipaddr);
sin.sin_port = ntohs(port);
int nLen = sizeof(sin);
if(len < 32768)
{
UDPData udpdata;
udpdata.index = index;
udpdata.part = 1;
udpdata.npart = 1;
udpdata.len = len;
memcpy(udpdata.data , data , len);
retlen = sendto(hSocket , (char *)&udpdata , sizeof(udpdata) ,0, (sockaddr*)&sin, nLen);
}
else
{
int n;
if(len % 32768)
n = len/32768 + 1;
else
n = len/32768;
for(int i=0 ; i<n ;i++)
{
UDPData udpdata;
udpdata.index = index;
udpdata.part = n;
udpdata.npart = i;
if(i == n-1)
{
udpdata.len = len-i*32768;
memcpy(&udpdata.data , data+i*32768 , len-i*32768);
}
else
{
udpdata.len = 32768;
memcpy(&udpdata.data , data+i*32768 , 32768);
}
retlen = sendto(hSocket , (char *)&udpdata , sizeof(udpdata) , 0,(sockaddr*)&sin, nLen);
}
}
index ++;
return retlen;
}
int UDPSessions::UDPRecv(char *& data)
{
int retlen = 0;
int fpart = 0;
UDPData udpdata;
sockaddr_in addr;
int nLen = sizeof(addr);
while(1)
{
int len = recvfrom(hSocket, (char *)&udpdata, sizeof(udpdata), 0, (sockaddr*)&addr, &nLen);
retlen += udpdata.len;
if(udpdata.part == 1) //只有一个分块
{
index = udpdata.index;
data = (char *)malloc(udpdata.len);
memcpy(data , &udpdata.data , udpdata.len);
break;
}
else if(udpdata.part > 1)
{
if(index == udpdata.index) //同一个包的块
{
if(fpart+1 == udpdata.npart) //顺序包
{
memcpy(data+udpdata.npart*32768 , &udpdata.data , udpdata.len);
fpart ++;
}
else
{
retlen = -1;
break;
}
if(udpdata.npart == udpdata.part-1) //最后一个块
{
break;
}
}
else //新的包
{
if(udpdata.npart == 0)
{
data = (char *)malloc(udpdata.part*32768);
memcpy(data , &udpdata.data , 32768);
index = udpdata.index;
fpart = 0;
}
else
{
retlen = -1;
break;
}
}
}
else
{
retlen = -1;
break;
}
}
return retlen ;
}