我已经看到许多关于send()
讨论底层协议的问题。我完全清楚,对于 TCP,任何消息都可能在发送时被分解成多个部分,并且不能保证接收者会在一次原子操作中获得消息。在这个问题中,我只讨论send()
系统调用与本地系统的网络层交互时的行为。
根据 POSIX 标准和send()
我阅读的文档,要发送的消息的长度由length参数指定。请注意:send()
发送一条消息,长度为length。更远:
如果发送套接字上没有可用空间来保存要传输的消息,并且套接字文件描述符没有
O_NONBLOCK
设置,send()
则应阻塞直到空间可用。如果发送套接字没有空间来保存要传输的消息,并且套接字文件描述符确实已O_NONBLOCK
设置,则将send()
失败。
我认为在这个定义中 send() 没有任何可能返回除-1
(这意味着没有数据在内核中排队等待传输)或length之外的任何值,这意味着整个消息在内核中排队等待传送。即,在我看来,在本地排队消息以在内核中传递方面send()
必须是原子的。
- 如果内核中的套接字队列中有足够的空间容纳整个消息并且没有信号发生(正常情况),则将其复制并返回length。
- 如果在此期间出现信号
send()
,则它必须返回-1
。显然,在这种情况下,我们不能将消息的一部分排队,因为我们不知道发送了多少。所以在这种情况下什么都不能发送。 - 如果内核中的套接字队列中没有足够的空间容纳整个消息并且套接字正在阻塞,那么根据上面的语句
send()
必须阻塞直到空间变得可用。然后消息将被排队并send()
返回长度。 - 如果内核中的套接字队列中没有足够的空间容纳整个消息并且套接字是非阻塞的,则
send()
必须失败(返回-1
)并将errno
设置为EAGAIN
orEWOULDBLOCK
。同样,由于我们返回-1
,很明显在这种情况下,消息的任何部分都不能排队。
我错过了什么吗?send() 是否有可能返回一个值>=0 && <length
?在什么情况下?非 POSIX/UNIX 系统呢?Windowssend()
实现是否符合此要求?