成功发送send()“原子”吗?

时间:2011-11-07 18:56:57

标签: sockets tcp atomicity

使用返回的数字成功调用send()是否等于size参数中指定的数量,是否保证不会发生“部分发送”?

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

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

更新 根据目前为止的答案,我的问题可以改写如下:

在调用send()之前,有没有办法通过电线发送数据包/数据?

2 个答案:

答案 0 :(得分:5)

  

使用返回的数字成功调用send()是否等于> size参数中指定的数量,以确保不会发生“部分发送”?

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

  

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

as send()只返回no。传递到本地TCP堆栈的字节数,而不是send()实际上是否发送任何东西,你无论如何都无法区分这两种情况。但是,是的,可能只有一些数据可以通过网络实现。即使本地缓冲区中有足够的空间,对等体也可能没有足够的空间。如果你发送2个字节,但是对等体只有1个字节的空间,可能会发送1个字节,另一个将驻留在本地tcp堆栈中,直到对等体有足够的空间。

(这是一个极端的例子,大多数TCP堆栈可以防止一次发送这么小的数据段,但是如果你尝试发送4k数据但同行只有3k的空间,则同样适用。)

  

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

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

编辑回答:

  

在send()调用返回之前,有没有办法通过线路发送数据包/数据?

是。这可能由于许多原因而发生。 e.g。

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

答案 1 :(得分:3)

虽然这取决于您使用的协议,但一般问题是

对于TCP,数据在内核中缓冲,然后由TCP分组化算法自行决定发送,这非常多毛 - 它保留了多个定时器,介意路径MTU试图避免IP分段。

对于UDP,如果您的数据报不超过链接帧大小(通常值为1472 = 1500以太网帧--20个字节的IP报头 - 8个字节的UDP报头),您只能假设这种“原子性”。否则,您的发送主机必须对数据报进行IP分段。

如果中间路由器的出站链路MTU小于数据包大小,则它仍然可以对传递的数据包进行IP分片。