0

我使用tcp协议处理客户端的请求,我发现在使用“发送”功能时出现了一些内容丢失的现象。代码是一样的:

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

发送函数总是成功的,_tcslen(cData) 的值等于 send_count,cData[send_count-1] 是 ']'。但是当我使用wireshark(一个捕获工具)来捕获socket发出的数据包时,我发现一些内容总是丢失,包括']'的字符。内容是用 JSON 协议封装的,所以 ']' 很重要。每次发送的总大小为 8900 字节。但是当我将请求项一次(之前是100)更改为50时,没有遗漏任何东西,发回的大小约为4000字节。我不知道为什么会这样。

从我的日志文件中,我确定名为'cData'的数组包含全部内容,但是为什么wireshark捕获的数据包中的内容不完整?

4

1 回答 1

0

看到你在使用 TCP,它已经看起来不对了。

首先,TCP 是流协议,它不适合一次性数据包(尤其是小数据包),但它的好处远不止使用 UDP 来代替。请记住,如果您无法控制 TPC,您只能确保您的请求得到正确处理,实际通信由 Winsock 库完成。

永远记住,发送函数 len 参数不是一个要求,它是一个关于你的缓冲区有多大以及你可以一次性发送多少的提示,它可能返回比你想要发送的少,这可能取决于很多因素如何它经常发生,假设您使用环回设备,它可能永远不会这样做,这意味着发送实际上会发送您请求的内容。在一个真实的网络中,它可能会以大约 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 是简单的日志记录功能,你可以弄清楚。

于 2013-10-19T16:07:41.547 回答