Winsock发送额外的数据

Winsock sends additional data

本文关键字:数据 Winsock      更新时间:2023-10-16

我正在用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);    
}

客户端是否会因为滞后而接收到错误的字节值?有什么办法解决这个问题吗?感谢您的帮助!

考虑这个例子:

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中。您不能保证,如果您对send进行n调用,您将对recv进行n调用以接收所有数据。

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

您的发送和接收函数都有一个错误。

您可以正确地跟踪发送/接收的总字节数,以便正确地退出循环,但在随后的send/recv调用中忘记了调整"buff"answers"size"的值。如果要发送的缓冲区必须通过多个要发送的调用进行传输,则会发送错误的数据。

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

它应该是:

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

同样,对于recv情况:

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

我不确定这是否是你的问题的原因,但我有一种感觉,当todda指出的场景是真的时,你的数据流就会被这个错误破坏。

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

我希望这能有所帮助。