amn*_*amn 6 sockets nonblocking send berkeley-sockets
我现在已经阅读了至少10次文档,并且还阅读了大约10个代码片段和完整程序,其中非阻塞套接字用于发送数据.问题是,有些教程要么适合初学者(Beejs fi),要么在他们的假设中非常草率; 那些不复杂的是专门的代码示例,无法解释他们为什么这么做.send
在我看来,即使是SO知识库也没有详尽地涵盖整个行为范围.我所追求的是有关fe的详细信息:
errno
或者只是在没有进一步调查的情况下丢弃连接?errno
是EWOULDBLOCK
,EAGAIN
或EINTR
(......其他)?errno
返回值是否值得检查> 0
?显然,该值表示"已发送"的数据量(在引号中,因为它确实是一个很长的过程,正确),但由于套接字是非阻塞的,这是否意味着可以立即发出另一个呼叫,或者,errno
再次,一个人应该等待下一个发送时机(使用select/poll/epoll)?errno
值?或者,也许send
将errno
在每次调用,返回值,而不管?这会使错误检查更容易......EINTR
,那么程序要采取什么样的良好,强健的行为呢?只需记录状态并在下一次发送时重试,比如EWOULDBLOCK
和EAGAIN
?EWOULDBLOCK
和 EAGAIN
?我们可以相信两者具有相同的价值,还是依赖于实施?send
返回EMSGSIZE
了流式套接字?如果没有,那么没有缓冲区大小太大,对吧?如果你能提供一个强大的非阻塞发送代码的例子,那将是绝对赞赏的.
这里有很多问题:
- 返回代码0的确切指示是什么,是否值得检查errno或者是否应该在没有进一步调查的情况下丢弃连接?
在POSIX系统上,send(2)永远不会返回0,除非您使用长度arg为0调用它.检查特定系统的文档以确保它遵循POSIX规范
- 获得负的返回值是否需要关闭连接变坏,或者仅仅是这样,除非errno是EWOULDBLOCK,EAGAIN或EINTR(......其他)?
不,-1返回值(唯一可能的负返回值)仅表示没有发送数据.你需要检查errno以查看为什么 - 请参阅send(2)手册页以获取所有可能的errno值的完整列表及其含义
- 当返回值> 0时,是否值得检查errno?显然,该值表示"已发送"的数据量(在引号中,因为它确实是一个很长的过程,正确),但由于套接字是非阻塞的,这是否意味着可以立即发出另一个调用,或者,再次依赖于errno ,应该等待下一次发送时机(使用select/poll/epoll)?
如果send返回成功(> 0),那么errno将保持不变并且将包含之前的任何内容(这可能是某些早期系统调用的错误).
- 基本上,首先检查返回值,然后才检查errno值吗?或者也许在每次通话时发送套装errno,无论如何返回值?这会使错误检查更容易......
首先检查返回值,然后检查错误,如果返回值为-1.如果你真的想要,可以在通话前将errno设置为0,然后再检查
- 如果有人获得EINTR,那么程序要采取什么样的良好,强健的行为呢?只需记录状态并在下一次发送时重试,例如EWOULDBLOCK和EAGAIN?
嗯,最简单的方法是禁用系统调用的中断,在这种情况下,你永远不会得到EINTR.像EWOULDBLOCK/EAGAIN一样对待它也很好.
- 是否检查EWOULDBLOCK和EAGAIN?我们可以相信两者具有相同的价值,还是依赖于实施?
取决于实施,但通常它们是相同的.有时,SysV与BSD仿真模式之间存在奇怪之处,可能会使它们不同,并且可能会发生
- 发送返回EMSGSIZE的流套接字?如果没有,那么没有缓冲区大小太大,对吧?
流套接字没有原子消息,EMSGSIZE仅用于原子消息,所以不,流套接字不能返回EMSGSIZE
- 返回值本身是否等于任何已知的错误代码?
唯一的错误代码是-1.成功是写入的字节数,所以,如果你可以写2 ^ 32-1(64位机器上或2 ^ 64-1)在32位机器上的字节,这将是一个问题,但你不能写下那么多字节(如果你尝试的话,你通常会获得EINVAL或EFAULT).