我使用tcp协议处理客户端的请求,我发现了一个现象,即在使用'send'功能时缺少一些内容。代码是同伴:
_stprintf(cData,"[%s]",send_back);
memset(send_back,0,sizeof(cData));
int send_count;
if((send_count=send(service_sock,cData,_tcslen(cData),0))!=SOCKET_ERROR){
fwrite(cData,sizeof(char),_tcslen(cData),hFile);
fflush(hFile);
g_log->print_log("%c%c%c%c",cData[0],cData[1],cData[2],cData[send_count-1]);
g_log->print_log("buffer len is :%d , send %d bytes",_tcslen(cData),send_count);
fclose(hFile);
memset(cData,0,sizeof(cData));
return true;
}
send函数总是成功的,_tcslen(cData)的值等于send_count,而cData [send_count-1]的值是']'。 但是当我使用wireshark(捕获工具)来捕获套接字发出的数据包时,我发现一些内容总是丢失,包括']'的字符。内容由JSON协议封装,因此']'很重要。每次发送的总大小为8900字节。但是当我将请求项一次(在100之前)更改为50时,没有任何遗漏,发送回的大小约为4000字节。 我不知道为什么会这样。
从我的日志文件中,我确定名为'cData'的数组包含总内容,但是为什么wireshark捕获的数据包中的内容不完整?
答案 0 :(得分:0)
看到你正在使用TCP,它看起来已经错了。
首先,TCP是流协议,不适用于一次性数据包(特别是小),但其好处远远大于仅使用UDP。 请记住,如果TPC无法控制,您只能确保正确处理您的请求,实际的通信是由Winsock库完成的。
永远记住send函数len参数是 NOT 一个要求它暗示你的缓冲区有多大以及你可以一次发送多少,它可能会返回少于你想发送的数量,这可能取决于很多因素它发生的频率,假设您使用它可能永远不会这样做的环回设备,这意味着发送将实际发送您请求的内容。在真实网络中,它可以一次性发送约90%或更低概率。
你必须确保你发送尽可能多的内容,即检查返回值,如果它没有发送你想要的那么多并且做同样的就再次调用send。另一方面有recv,请调用recv,直到获得所需数据。只有在您确切知道要通过网络发送多少数据时,此方法才有效。
至于丢失数据,TCP,我会说几乎总是发送数据,假设您检查了send的返回值。如果存在网络问题,例如丢失数据,您将看到TCP重新传输数据包。
对于您发送数据的方式,这更合适,这是为了确保您真正发送所需的数据量:
xint xsend(SOCKET s,const char* buf,xint len)
{
xint lastSize;
xint result;
if (len==0 || s==(SOCKET)NULL || buf==(const char*)NULL)
return SOCKET_ERROR;
lastSize=0;
result=0;
do
{
result=send(s,buf+lastSize,len-lastSize,0);
if (result==0)
return 0;
if (result==SOCKET_ERROR)
return SOCKET_ERROR;
if (result==len)
return len;
if (result>len)
{
xlog(1,"xsend : socket sent too much data [ %i of %i ]",result,len);
return SOCKET_ERROR;
}
lastSize+=result;
if (lastSize>len)
{
xlog(1,"xsend : socket sent too much data ( overall ) [ %i of %i ]",result,len);
return SOCKET_ERROR;
}
if (lastSize==len)
return len;
}
while (1);
xlog(2,"failed to do xsend");
return SOCKET_ERROR;
}
这段代码只是我的一个项目的复制粘贴,xlog是简单的日志记录功能,你可以搞清楚。