成功的 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?
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不,有可能部分数据通过线路传递,而另一部分仅复制到本地 TCP 堆栈的内部缓冲区中。 send() 将返回编号。传递到本地 TCP 堆栈的字节数,而不是编号。传递到线路的字节数(即使数据到达线路,也可能无法到达对等点)。
因为 send() 只返回编号。传递到本地 TCP 堆栈的字节数,而不是 send() 是否实际发送任何内容,无论如何你都无法真正区分这两种情况。但是,是的,可能只有一些数据通过网络传输。即使本地缓冲区有足够的空间,对等方也可能没有足够的空间。如果您发送 2 个字节,但对等方只剩下 1 个字节的空间,则可能会发送 1 个字节,另一个字节将驻留在本地 tcp 堆栈中,直到对等方再次有足够的空间。
(这是一个极端的例子,大多数 TCP 堆栈都会防止一次发送如此小的数据段,但如果您尝试发送 4k 数据但对等方只有 3k 的空间,这同样适用)。
这只有在您的套接字是非阻塞的情况下才会发生。如果它阻塞并且本地缓冲区已满,则 send() 将等待,直到本地缓冲区再次有空间(或者,它可能返回
如果部分数据已交付,但同时发生错误,则进行短暂计数。)
编辑回答:
是的。发生这种情况的原因有很多。
例如,
在发送进程从 send() 返回之前运行。
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).
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).
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:
Yes. That might happen for many reasons.
e.g.
run before that sending process returns from send().
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.