gevent tcp套接字已断开但可以发送数据

时间:2016-03-21 19:15:01

标签: sockets gevent

我有一个使用gevent编写的小型HTTP服务器,它接受传入的连接并使用每个连接的greenlet发回数据。当(本地)客户端死于服务器端写入客户端成功,尽管套接字处于CLOSE_WAIT状态:

TIdHTTP

现在,我希望我使用gevent.socket.socket创建的套接字的send方法失败并出现异常,但我没有得到!

TIdHTTP::OnRedirect

我的期望不正确吗?如果没有,这里可能出现什么问题?

1 个答案:

答案 0 :(得分:0)

经过一些调试后,我发现我对套接字API在TCP之上的行为方式的期望是不正确的。潜在读者可能需要仔细阅读 TCP option SO_LINGER (zero) - when it's required

要带走的东西:

  1. 客户端关闭()将FIN发送到服务器,这大致意味着"我完成了向您发送数据"。这意味着服务器可能仍然能够发回数据。
  2. 如果服务器在客户端关闭后尝试写入,则写入将成功(返回从用户空间复制到内核空间的字节数),数据将被发送到客户端,客户端将发回RST因为其套接字仍然处于TIMEWAIT状态(除非你使用SO_LINGER为零禁用了这个,这就是为什么你真的不想将SO_LINGER设置为零),服务器套接字状态将被更新为CLOSED。
  3. 如果服务器在从客户端收到RST后尝试第二次写入,则写入将失败。
  4. 如果服务器在客户端关闭后尝试recv,则recv将返回零以指示流结束。
  5. 总结一下,这意味着我的服务器需要使用作为recv()== 0返回的流末尾通知作为客户端已关闭其连接并相应地采取行动的标志(即关闭相关插座)。