Winsock发送其他数据

时间:2012-01-25 23:41:58

标签: c++ sockets client-server winsock send

我正在使用winsock用c ++编写一个小型客户端/服务器应用程序,我无法解释正在发生的一些事情。 我写了两个基本函数,通过TCP连接发送/接收所有数据..

bool sending(SOCKET source, char* buff, int size, int flags = 0)
{
    int sent = 0;
    int totalst = 0;
    int total = size;
    while(totalst != total)
    {
        sent = send(source, buff+totalst, size-totalst, flags);
        if(sent > 0)
        {
            totalst += sent;
        }
        if(sent == SOCKET_ERROR)
        {
            return false;
        }       
    }   
    return true;
}

bool receive(SOCKET source, char* buff, int size, int flags = 0)
{
    int rec = 0;
    int totalrc = 0;
    int total = size;
    while(totalrc != total)
    {
        rec = recv(source, buff+totalrc, size-totalrc, flags);
        if(rec > 0)
        {
            totalrc += rec;
        }
        if(rec == SOCKET_ERROR)
        {
            return false;
        }
    }
    return true;
}

服务器发出一个整数,其中包含将跟随它的数据块的大小。在我的情况下,这个数据块的大小不应该改变,它应该总是92600字节,但有时客户端会收到92604而是字节。奇怪的是,如果我在发送块大小和块本身(使用Sleep)之后让服务器等待,它总是会发送我期望的内容。

int i=0;                    
while(i < 100)
{
    i++;
    dat = getData();                                
    len = sizeof(dat);
    sending(source, (char*)&len, sizeof(len));
    sending(source, dat, len);
    Sleep(200);    
}

由于滞后,客户端是否会收到不正确的字节值? 有没有办法解决这个问题? 任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:2)

考虑这个例子:

char *x = "!";
send(socket, x, 1); // destination, buffer, size
send(socket, x, 1);
send(socket, x, 1);
send(socket, x, 1);

你期望在这里发生什么?

char buffer[4];
recv(socket, buffer, 4); // source, buffer, size

实际上,四个send发送的数据可以收到一个recv。您无法保证,如果您对n进行send来电,则会n拨打recv来接收所有数据。

正如nos所评论的那样,TCP没有实现消息边界。这是你的工作,在应用层。 Winsock不会发送额外的数据。

答案 1 :(得分:0)

您的发送和接收功能都存在错误。

您正确地跟踪发送/接收的总字节数,以便您可以退出循环,但是在后续的send / recv调用中忘记调整“buff”和“size”的值。如果要发送的缓冲区必须通过多次调用发送,您将发送错误的数据。

同样,如果需要多次调用“recv”,您将覆盖在缓冲区开头复制的数据。

应该是:

sent = send(source, buff+totalst, size-totalst, 0);

同样对于recv案例:

rec = recv(source, buff + totalrc, size-totalrc, 0);

我不确定这是否会导致您的问题,但我有一种感觉,当todda指出的情况为真时,您的数据流会因此错误而被破坏。

有意义吗?此外,您应该准备好处理recv()将返回0的情况。

我希望这会有所帮助。