Socket编程send()函数的返回值

3
在 Linux 或 Windows 套接字编程中,我知道 read 函数会返回成功接收的字节数。但是这个返回值可能小于请求的长度(例如,如果接收缓冲区只有 50 字节,则 read(sd, buf, 100) 可能只返回 50)。请问这种情况是否可能发生?
send(sd, buf, 100);

返回1〜99之间的值?如果是,什么时候会出现这种情况?我想知道具体的示例情况。

提前感谢你。

1个回答

5
请参阅官方规范,如涉及Winsock,请查看man页面或MSDN文档。
在实际应用中,阻塞模式下的send()会发送所有数据,不管文档说了什么,除非发生错误,此时不会发送任何数据。
在非阻塞模式下,它会发送适合套接字发送缓冲区的任何内容,并返回长度大于0的值。如果套接字发送缓冲区已满,则返回-1,并设置errno = EWOULDBLOCK/EAGAIN。

谢谢,这正是我所假设的。你证实了它,谢谢。 - daehee
我没有测试过,但我想象如果你通过阻塞 I/O 发送非常大的缓冲区(例如每个 send() 调用超过 65KB),那么它可能会发送部分数据,然后遇到错误(例如远程对等方关闭了连接)。在这种情况下,我认为 send() 唯一有用的行为方式是返回发送的字节数,这将小于缓冲区大小。这在实践中并不经常发生,只因为大多数程序不尝试在一个调用中发送太多数据。 - Jeremy Friesner
2
@JeremyFriesner 根据规范是可能的。但实际上并不会发生,这不是因为“大多数程序不尝试发送太多数据”,而是因为所有内核中都是这样实现 send() 函数的。 - user207421
嗯,好的。如果send()已经发送了800KB缓冲区的200KB,然后接收应用程序关闭了套接字的一端,那么send()会做什么?此时,send()会返回0并假装没有成功发送任何内容吗?我想我必须自己尝试一下才能知道... - Jeremy Friesner
好的,我尝试了一下(通过单个send()调用将20MB缓冲区通过TCP发送到本地主机上的另一个程序),并验证了EJP的正确性 - 至少在MacOS/X 10.8.2下,如果无法发送整个缓冲区,阻塞的send()仍然会返回-1,而不管实际到达接收方的字节数是多少。虽然这不是我实现的方式,但事实就是如此。 :P - Jeremy Friesner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接