【发布时间】:2013-11-10 21:50:20
【问题描述】:
我看到很多关于send() 的问题都在讨论底层协议。我完全清楚,对于 TCP,任何消息都可能在发送时被分解成多个部分,并且不能保证接收者会在一次原子操作中获得消息。在这个问题中,我只讨论send() 系统调用在与本地系统的网络层交互时的行为。
根据 POSIX 标准和我阅读过的send() 文档,要发送的消息的长度由长度参数指定。请注意:send() 发送 一个 消息,长度为 length。进一步:
如果发送套接字上没有可用空间来保存消息 被传输,并且套接字文件描述符没有
O_NONBLOCK设置,send()将阻塞直到空间可用。如果空间 无法在发送套接字处保存消息 传输,并且套接字文件描述符确实设置了O_NONBLOCK,send()会失败。
我认为在这个定义中 send() 没有任何可能返回除 -1 之外的任何值(这意味着内核中没有数据排队等待传输)或 length ,这意味着整个消息在内核中排队等待传输。即,在我看来,send() 必须是原子的相对于在内核中对消息进行本地排队。
- 如果内核中的套接字队列中有足够的空间容纳整个消息并且没有信号出现(正常情况),则会复制它并返回 length。
- 如果在
send()期间出现信号,则它必须返回-1。显然,在这种情况下,我们不能将消息的一部分排队,因为我们不知道发送了多少。因此,在这种情况下无法发送任何内容。 - 如果内核中的套接字队列没有足够的空间容纳整个消息并且套接字正在阻塞,那么根据上面的语句
send()必须阻塞直到空间可用。然后消息将被排队,send()返回 length。 - 如果内核中的套接字队列中没有足够的空间容纳整个消息并且套接字是非阻塞的,那么
send()必须失败(返回-1)并且errno将被设置为@987654338 @ 或EWOULDBLOCK。同样,由于我们返回-1,很明显在这种情况下,消息的任何部分都不能排队。
我错过了什么吗? send() 是否可以返回 >=0 && <length 的值?在什么情况下?非 POSIX/UNIX 系统呢? Windows send() 的实现是否符合这个?
【问题讨论】:
-
似乎有些模棱两可。虽然
send()应该等价于sendto()如果套接字指的是连接模式套接字,POSIX 也说send()等价于write()如果flags为0。非阻塞或中断阻塞write()允许返回一个短值。