有人能给我一个很好的解释非阻塞套接字的"发送"行为吗?

amn*_*amn 6 sockets nonblocking send berkeley-sockets

我现在已经阅读了至少10次文档,并且还阅读了大约10个代码片段和完整程序,其中非阻塞套接字用于发送数据.问题是,有些教程要么适合初学者(Beejs fi),要么在他们的假设中非常草率; 那些不复杂的是专门的代码示例,无法解释他们为什么这么做.send在我看来,即使是SO知识库也没有详尽地涵盖整个行为范围.我所追求的是有关fe的详细信息:

  • 返回代码0的确切含义是什么,是否值得检查,errno或者只是在没有进一步调查的情况下丢弃连接?
  • 获得负回报值是否需要关闭连接变坏,或者只是这样,除非errnoEWOULDBLOCK,EAGAINEINTR(......其他)?
  • errno返回值是否值得检查> 0?显然,该值表示"已发送"的数据量(在引号中,因为它确实是一个很长的过程,正确),但由于套接字是非阻塞的,这是否意味着可以立即发出另一个呼叫,或者,errno再次,一个人应该等待下一个发送时机(使用select/poll/epoll)?
  • 基本上,首先检查返回值,然后才检查errno值?或者,也许senderrno在每次调用,返回值,而不管?这会使错误检查更容易......
  • 如果有人获得EINTR,那么程序要采取什么样的良好,强健的行为呢?只需记录状态并在下一次发送时重试,比如EWOULDBLOCKEAGAIN
  • 是否为一个检查 EWOULDBLOCK EAGAIN?我们可以相信两者具有相同的价值,还是依赖于实施?
  • 是否send返回EMSGSIZE了流式套接字?如果没有,那么没有缓冲区大小太大,对吧?
  • 返回值本身是否等于任何已知的错误代码?

如果你能提供一个强大的非阻塞发送代码的例子,那将是绝对赞赏的.

Chr*_*odd 9

这里有很多问题:

  • 返回代码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).