成功的 send() 是“原子的”吗?

发布于 2024-12-14 06:56:42 字数 775 浏览 1 评论 0原文

Does a successful call to send() with the number returned equal to the amount specified in the size parameter guarantee that no "partial sends" will occur?

Or is there some way that the OS might be interrupted while servicing the system call, send part of the data, wait for a possibly long time, then send the rest and return without notifying me with a smaller return value?

I'm not talking about a case where there is not enough room in the kernel buffer; I realize that I would then get a smaller return value and have to try again.

更新: Based on the answers so far, my question could be rephrased as follows:

Is there any way for packets/data to be sent over the wire before the call to send() returns?

Does a successful call to send() with the number returned equal to the amount specified in the size parameter guarantee that no "partial sends" will occur?

Or is there some way that the OS might be interrupted while servicing the system call, send part of the data, wait for a possibly long time, then send the rest and return without notifying me with a smaller return value?

I'm not talking about a case where there is not enough room in the kernel buffer; I realize that I would then get a smaller return value and have to try again.

Update:
Based on the answers so far, my question could be rephrased as follows:

Is there any way for packets/data to be sent over the wire before the call to send() returns?

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

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

发布评论

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

评论(2

裸钻 2024-12-21 06:56:42

成功调用 send() 并且返回的数量等于>大小参数中指定的数量是否可以保证不会发生“部分发送”?

不,有可能部分数据通过线路传递,而另一部分仅复制到本地 TCP 堆栈的内部缓冲区中。 send() 将返回编号。传递到本地 TCP 堆栈的字节数,而不是编号。传递到线路的字节数(即使数据到达线路,也可能无法到达对等点)。

或者是否有某种方式可以使操作系统在服务系统调用时被中断,发送部分数据,等待可能很长时间,然后发送其余部分并返回,而不用较小的返回值通知我?

因为 send() 只返回编号。传递到本地 TCP 堆栈的字节数,而不是 send() 是否实际发送任何内容,无论如何你都无法真正区分这两种情况。但是,是的,可能只有一些数据通过网络传输。即使本地缓冲区有足够的空间,对等方也可能没有足够的空间。如果您发送 2 个字节,但对等方只剩下 1 个字节的空间,则可能会发送 1 个字节,另一个字节将驻留在本地 tcp 堆栈中,直到对等方再次有足够的空间。

(这是一个极端的例子,大多数 TCP 堆栈都会防止一次发送如此小的数据段,但如果您尝试发送 4k 数据但对等方只有 3k 的空间,这同样适用)。

我不是在谈论内核缓冲区空间不足的情况;而是在讨论内核缓冲区空间不足的情况。我意识到我会得到一个较小的返回值并且必须重试

这只有在您的套接字是非阻塞的情况下才会发生。如果它阻塞并且本地缓冲区已满,则 send() 将等待,直到本地缓冲区再次有空间(或者,它可能返回
如果部分数据已交付,但同时发生错误,则进行短暂计数。)

编辑回答:

在调用 send() 返回之前,有什么方法可以通过线路发送数据包/数据吗?

是的。发生这种情况的原因有很多。
例如,

  • 本地缓冲区被最近的 send() 调用填满,并且您使用阻塞 I/O。
  • TCP 堆栈通过线路发送数据,但决定安排其他进程来
    在发送进程从 send() 返回之前运行。

Does a successful call to send() with the number returned equal to the amount specified in >the size parameter guarantee that no "partial sends" will occur?

No, it's possible that parts of your data gets passed over the wire, and another part only goes as far as being copied into the internal buffers of the local TCP stack. send() will return the no. of bytes passed to the local TCP stack, not the no. of bytes that gets passed onto the wire (and even if the data reaches the wire, it might not reach the peer).

Or is there some way that the OS might be interrupted while servicing the system call, send part of the data, wait for a possibly long time, then send the rest and return without notifying me with a smaller return value?

As send() only returns the no. of bytes passed into the local TCP stack, not whether send() actually sends anything, you can't really distinguish these two cases anyway. But yes, it's possibly only some data makes it over the wire. Even if there's enough space in the local buffer, the peer might not have enough space. If you send 2 bytes, but the peer only has room for 1 more byte, 1 byte might be sent, the other will reside in the local tcp stack until the peer has enough room again.

(That's an extreme example, most TCP stacks protects against sending such small segments of data at a time, but the same applies if you try to send 4k of data but the peer only have room for 3k).

I'm not talking about a case where there is not enough room in the kernel buffer; I realize that I would then get a smaller return value and have to try again

That will only happen if your socket is non-blocking. If it's blocking and the local buffers are full, send() will wait until there's room in the local buffers again (or, it might return
a short count if parts of the data was delivered, but an error occured in the mean time.)

Edit to answer:

Is there any way for packets/data to be sent over the wire before the call to send() returns?

Yes. That might happen for many reasons.
e.g.

  • The local buffers gets filled up by that recent send() call, and you use blocking I/O.
  • The TCP stack sends your data over the wire but decides to schedule other processes to
    run before that sending process returns from send().
杀手六號 2024-12-21 06:56:42

continue

Though this depends on the protocol you are using, the general question is no.

For TCP the data gets buffered inside the kernel and then sent out at the discretion of the TCP packetization algorithm, which is pretty hairy - it keeps multiple timers, minds path MTU trying to avoid IP fragmentation.

For UDP you can only assume this kind of "atomicity" if your datagram does not exceed link frame size (usual value is 1472 = 1500 of ethernet frame - 20 bytes of IP header - 8 bytes of UDP header). Otherwise your sending host will have to IP-fragment the datagram.

Then intermediate routers can still IP-fragment the passing packet if their outgoing link MTU is less then the packet size.

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