Winsock 发送附加数据

发布于 12-29 12:34 字数 1383 浏览 4 评论 0原文

我正在用 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 字节。奇怪的是,如果我在发送块大小和块本身(带有睡眠)后让服务器等待,它总是发送我期望的内容。

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

客户端是否会因为滞后而收到不正确的字节值? 有什么办法可以解决这个问题吗? 任何帮助表示赞赏!

I'm writing a small client/server application in c++ with winsock and I can't explain a few things that are happening..
I wrote 2 basic functions that send/receive all the data through a TCP connection..

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

The server sends out an integer that contains the size of the data block that will follow it.. This size of the data block in my case shouldn't change, it should always be 92600 bytes, but sometimes the client receives 92604 bytes instead. The odd thing is that if I make the server wait after sending the bock size and the block itself(with Sleep) it always sends what I would expect..

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

Can it bee that the client receives the incorrect value of bytes because of lag ?
Is there any way of fixing this?
Any help is appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

江南烟雨〆相思醉2025-01-05 12:34:21

考虑这个例子:

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 不会发送额外的数据,而是您发送。

Consider this example:

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

What do you expect to happen here?

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

In practice, the data sent by four send's can be received into one recv. You don't have any guarantee that if you make n calls to send you will make n calls to recv to recieve all the data.

As nos has commented, TCP doesn't implement message boundaries. That's your job, on the application layer. Winsock doesn't send additional data, you do.

生生漫2025-01-05 12:34:21

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

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

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

它应该是:

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

对于recv情况也是如此:

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

我不确定这是否会导致您的问题,但我有一种感觉,当todda指出的情况是正确的时,那么您的数据流就会被这个错误损坏。

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

我希望这会有所帮助。

You have a bug in both your sending and receiving function.

You properly keep track of the total bytes sent/received so that you propertly exit your loop, but you forget to adjust the value of "buff" and "size" in subsequent calls to send/recv. If the buffer to send has to get transmitted with multiple calls to send, you'll send the wrong data.

Likewise, if multiple calls to "recv" are needed, you'll overwrite the data copied at the start of the buffer.

It should read:

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

Likewise for the recv case:

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

I'm not sure if this is causing your issue, but I have a feeling when the scenario pointed out by todda is true, then your data streams are getting corrupted by this bug.

Make sense? Also, you should be prepared to handle the case where recv() will return 0.

I hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文