函数'send'的某些内容缺失

时间:2013-10-09 09:27:13

标签: windows tcp winsock send

我使用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捕获的数据包中的内容不完整?

1 个答案:

答案 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是简单的日志记录功能,你可以搞清楚。