为什么SO_RCVTIMEO从侦听套接字继承到接受套接字?

时间:2013-04-25 12:54:33

标签: c++ python linux sockets

除了Python documentation

之外,我找不到任何相关文档
  

18.1.4.2。超时和接受方法

     

如果getdefaulttimeout()不是None,则accept()方法返回的套接字会继承该超时。否则,行为取决于侦听套接字的设置:

     

如果侦听套接字处于阻塞模式或超时模式,accept()返回的套接字处于阻塞模式;

     

如果侦听套接字处于非阻塞模式,accept()返回的套接字是阻塞还是非阻塞模式是依赖于操作系统的。如果要确保跨平台行为,建议您手动覆盖此设置。

我已经阅读了这个[问题]:Are socket options inherited across accept() from the listening socket?,我认为最终判决仍然是实施定义的。我想在平台上进行测试比从每个内核读取源代码更容易。

这里明确说明了超时选项是继承的。但是在接受(2)的手册页上,没有提到这一点。当我在我的一个盒子(嵌入式Linux盒子)上调试一些C ++代码时,我发现这非常令人震惊。我希望接受的套接字不要继承这个选项。

我在哪里可以找到这个问题的明确答案?

2 个答案:

答案 0 :(得分:2)

如果这是一个C问题而不是Python问题,我不会根据Python文档得出SO_RCVTIMEO继承accept(2)的任何结论。我想你可能误解了Python文档,因为他们......

  1. 从未明确提及SO_RCVTIMEO选项
  2. 永远不会说超时值是从侦听套接字继承的,而是从setdefaulttimeout()
  3. 设置的全局超时值继承的

    查看socketmodule.c的源代码,Python甚至不使用SO_RCVTIMEO套接字选项。相反,它将超时值存储在套接字对象的内部表示中,并在调用select(2)poll(2)时使用它。

    我怀疑Python有点奇怪的实现的基本原理是它被设计为在许多平台上运行,其中一些平台不支持SO_RCVTIMEO选项。唯一的参考SO_RCVTIMEO位于第4773行......

    #ifdef SO_RCVTIMEO
    PyModule_AddIntConstant(m, "SO_RCVTIMEO", SO_RCVTIMEO);
    #endif
    

    ...它被预处理器指令包围,以防SO_RCVTIMEO未在编译它的平台上定义。

    至于为什么Python文档说...

      

    ... accept()方法返回的套接字继承了超时...

    ...那是因为Python的accept()的内部实现明确地将新套接字的内部超时值设置为第732行的默认超时值...

    s->sock_timeout = defaulttimeout;
    

    至于原来的问题......

      

    我在哪里可以找到这个问题的明确答案?

    ...我想你必须在找到它之前搜索内核源代码,但它可能更简单,只是不做任何关于继承内容的假设,并明确覆盖你从默认值中更改的任何选项。 accept(2)返回的新套接字FD上的父套接字FD。

答案 1 :(得分:1)

BSD套接字API执行此操作。接受的套接字继承了侦听套接字中的所有内容:接收缓冲区大小,超时,KEEPALIVE,close-on-exec。一些更高级别的API(如Java)会做更多的工作来撤消它,例如读取超时。