unix 套接字:如何通过一次“发送”发送真正的大数据称呼?

发布于 2024-08-08 04:29:03 字数 363 浏览 6 评论 0原文

我正在使用 unix scoket 进行数据传输(SOCK_STREAM 模式),

我需要发送超过 100k 个字符的字符串。首先,我发送字符串的长度 - 它是 sizeof(int) 字节。

length = strlen(s)
send(sd, length, sizeof(int))

然后我发送整个字符串

bytesSend = send(sd, s, length)

,但令我惊讶的是“bytesSend”小于“length”。

请注意,当我发送不太大的字符串时,这效果很好。 系统调用“发送”可能存在一些我一直缺少的限制......

I'm using unix scoket for data transferring (SOCK_STREAM mode)

I need to send a string of more than 100k chars. Firstly, I send length of a string - it's sizeof(int) bytes.

length = strlen(s)
send(sd, length, sizeof(int))

Then I send the whole string

bytesSend = send(sd, s, length)

but for my surprise "bytesSend" is less than "length".

Note, that this works fine when I send not so big strings.
May be there exist some limitations for system call "send" that I've been missing ...

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

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

发布评论

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

评论(2

落花浅忆 2024-08-15 04:29:03

send 系统调用应该,因为程序可能还有其他有用的事情要做。当然,您不想等待数据发送出去并等待另一台计算机发送回复 - 这将导致可怕的吞吐量。

因此,send 真正所做的就是将一些数据排队等待发送,并将控制权返回给程序。内核可以将整个消息复制到内核内存中,但这会消耗大量内核内存(不好)。

相反,内核仅将合理数量的消息排队。程序负责重新尝试发送剩余数据。

在您的情况下,使用循环发送第一次未发送的数据。

while(length > 0) {
    bytesSent = send(sd, s, length);
    if (bytesSent == 0)
        break; //socket probably closed
    else if (bytesSent < 0)
        break; //handle errors appropriately
    s += bytesSent;
    length -= bytesSent;
}

在接收端,您可能需要做同样的事情。

The send system call is supposed to be fast, because the program may have other things useful things to do. Certainly you do not want to wait for the data to be sent out and the other computer to send a reply - that would lead to terrible throughput.

So, all send really does is queues some data for sending and returns control to the program. The kernel could copy the entire message into kernel memory, but this would consume a lot of kernel memory (not good).

Instead, the kernel only queues as much of the message as is reasonable. It is the program's responsibility to re-attempt sending of the remaining data.

In your case, use a loop to send the data that did not get sent the first time.

while(length > 0) {
    bytesSent = send(sd, s, length);
    if (bytesSent == 0)
        break; //socket probably closed
    else if (bytesSent < 0)
        break; //handle errors appropriately
    s += bytesSent;
    length -= bytesSent;
}

At the receiving end you will likely need to do the same thing.

最丧也最甜 2024-08-15 04:29:03

您最初的 send() 调用是错误的。您需要向 send() 传递数据的地址,即:

bytesSend = send(sd, &length, sizeof(int))

此外,这会遇到一些经典风险,如字节顺序、各种平台上的 int 大小等。

Your initial send() call is wrong. You need to pass send() the address of the data, i.e.:

bytesSend = send(sd, &length, sizeof(int))

Also, this runs into some classical risks, with endianness, size of int on various platforms, et cetera.

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