我已经看到了一些关于send()它的问题,讨论了底层协议.我完全清楚,对于TCP,任何消息都可能在发送时被分解为部分,并且无法保证接收器将在一次原子操作中获取消息.在这个问题中,我只谈论send()系统调用的行为,因为它与本地系统的网络层交互.
根据POSIX标准和send()我读过的文档,要发送的消息的长度由 length 参数指定.请注意:send()发送一条长度为length的消息.进一步:
如果发送套接字上没有空间来保存要传输的消息,并且套接字文件描述符没有
O_NONBLOCK设置,send()则应阻塞直到空间可用.如果发送套接字上没有空间来保存要传输的消息,并且套接字文件描述符确实已O_NONBLOCK设置,则将send()失败.
我没有看到send()在这个定义中有任何可能返回除了-1(这意味着没有数据在内核中排队等待传输)或长度之外的任何值,这意味着整个消息在内核中排队等待传输.也就是说,在我看来,对于本地排队消息以便在内核中传递,send()必须是原子的.
send(),则必须返回-1.显然,在这种情况下我们不能排队部分消息,因为我们不知道发送了多少消息.因此在这种情况下无法发送任何内容.send()必须阻塞,直到空间可用.然后消息将排队并send()返回长度.send()必须失败(返回-1)并将errno设置为EAGAIN或EWOULDBLOCK.同样,因为我们返回-1它很清楚,在这种情况下,消息的任何部分都不能排队.我错过了什么吗?send()是否可以返回一个值>=0 && <length?在什么情况下?那么非POSIX/UNIX系统呢?Windows send()实现是否符合此要求?
R..*_*R.. 10
你的观点2过于简化了.send返回大于零但小于length的值的正常条件(注意,正如其他人所说的那样,除了长度参数为零之外,它永远不会返回零)是消息足够长以导致阻塞,并且一些内容已经发送后,中断信号到达.在这种情况下,send不能失败EINTR(因为这会阻止应用程序知道它已经成功发送了一些数据)并且它无法重新阻塞(因为信号正在中断,并且整个过程就是没有阻塞) ,因此它必须返回已发送的字节数,这小于请求的总长度.
根据 Posix 规范和我 30 年来见过的所有man 2 send pages,是的,send()可以返回任何 > 0 和 <= 的值length。请注意,它不能返回零。
根据几年前关于 news:comp.protocols.tcp-ip 的讨论,所有 TCP 实现者都在那里,send()直到将所有数据传输到套接字发送缓冲区之前,阻塞实际上不会返回:换句话说,返回值是 -1 或length.一致认为这适用于所有已知的实现,也适用于write(), writev(), sendmsg(), writev(),
| 归档时间: |
|
| 查看次数: |
7417 次 |
| 最近记录: |