看了下以前做socket通信写的代码,发现没有考虑到"粘包"问题.我觉得解决这个问题无非两点:1.定义一个两端通信的信令结构;2.应用层每次能从传输层缓存中拆分出这个结构.下面是部分代码,不对的地方还请各位高手指正!#define MAX_DATA_LEN 1024 // 信令中数据区长度
#define MAX_PARAMS_LEN 16 // 无符号字节参数区长度
#define MAX_BUF_LEN 2048 // 应用层接收/发送缓存区大小// 信令格式
struct _tagPACK_DATA
{
#define PACK_DATA_LEN sizeof _tagPACK_DATA // 信令总长度
char csignal; // 信令操作码
int iparam; // 整型参数
char cparams[MAX_PARAMS_LEN]; // 字节型参数
char cdata[MAX_DATA_LEN]; // 数据区
};// 接收/发送缓存结构
struct _tagDATA_BUF
{
#define DATA_BUF_LEN sizeof _tagDATA_BUF // 缓存总大小
char cbuf[MAX_BUF_LEN]; // 缓存区
int isize; // 已发送字节数
};...
while(TRUE)
{
DWORD dwEvent = WSAWaitForMultipleEvents(...); // 等待传输层绑定的事件对象
...
BUF.isize += recv( sock, BUF.cbuf + BUF.isize, PACK_DATA_LEN - BUF.isize, 0 ); // 从远程套接字的接收缓存"剥离"指定大小的数据
if( BUF.isize < PACK_DATA_LEN ) continue; // 如果接收的数据大小小于信令长度,则等待客户端发送此信令剩余部分的数据,当然这
memcpy( &PACK, BUF.cbuf, PACK_DATA_LEN ); // 些数据是和下一个信令"粘"在一起的.装配完一个信令后,将其拷贝到信令结构.
...
}
...
#define MAX_PARAMS_LEN 16 // 无符号字节参数区长度
#define MAX_BUF_LEN 2048 // 应用层接收/发送缓存区大小// 信令格式
struct _tagPACK_DATA
{
#define PACK_DATA_LEN sizeof _tagPACK_DATA // 信令总长度
char csignal; // 信令操作码
int iparam; // 整型参数
char cparams[MAX_PARAMS_LEN]; // 字节型参数
char cdata[MAX_DATA_LEN]; // 数据区
};// 接收/发送缓存结构
struct _tagDATA_BUF
{
#define DATA_BUF_LEN sizeof _tagDATA_BUF // 缓存总大小
char cbuf[MAX_BUF_LEN]; // 缓存区
int isize; // 已发送字节数
};...
while(TRUE)
{
DWORD dwEvent = WSAWaitForMultipleEvents(...); // 等待传输层绑定的事件对象
...
BUF.isize += recv( sock, BUF.cbuf + BUF.isize, PACK_DATA_LEN - BUF.isize, 0 ); // 从远程套接字的接收缓存"剥离"指定大小的数据
if( BUF.isize < PACK_DATA_LEN ) continue; // 如果接收的数据大小小于信令长度,则等待客户端发送此信令剩余部分的数据,当然这
memcpy( &PACK, BUF.cbuf, PACK_DATA_LEN ); // 些数据是和下一个信令"粘"在一起的.装配完一个信令后,将其拷贝到信令结构.
...
}
...
{
UINT packLen;
char buf[1];
}PACK_DATA,*PPACK_DATA;typedef struct _SIGNAL
{
char csignal; // 信令操作码
int iparam; // 整型参数
char cparams[MAX_PARAMS_LEN]; // 字节型参数
char cdata[1]; // 数据区
}SIGNAL,*PSIGNAL;
UINT readLen=0,totalRead=0,totalLen=0;
PPACK_DATA pdata;
while(TRUE)
{
DWORD dwEvent = WSAWaitForMultipleEvents(...); // 等待传输层绑定的事件对象
...
if(totalRead==0)
{
readLen=recv(sock,(char *)&totalLen,4,0);//首先接收字本次包的大小;
totalRead+=readlen;
pdata=(PPACK_DATA)malloc(totalLen);
pdata->packLen=totalLen;
}
else
{
readLen=recv(sock,(char *)(pdata+totalRead,totalLen-totalRead,0);
totalRead+=readLen;
if(totalRead>=totalLen)
{
PSIGNAL ps=(PSIGNAL)pdata->buf;
//处理你的数据
readLen=totalRead=TotalLen=0;
}
}
...
}
唉,怪不得csdn人气越来越差,翻来覆去总是那几个问题。