1

除了一些 Python 文档之外,我找不到任何关于此的文档

18.1.4.2。超时和接受方法

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

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

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

我已阅读此 [问题]:套接字选项是否从侦听套接字跨接受()继承?,我认为最终的判决仍然是实现定义的。我想在平台上进行测试比从每个内核读取源代码更容易。

这里清楚地表明超时选项是继承的。但是在 accept(2) 的联机帮助页上,没有提到这一点。当我在我的一个盒子(嵌入式 Linux 盒子)上调试一些 C++ 代码时,我发现这非常令人震惊。我希望接受的套接字不会继承此选项。

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

4

2 回答 2

2

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

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

查看 的源代码socketmodule.c,Python 甚至没有使用SO_RCVTIMEOsocket 选项。相反,它将超时值存储在它自己的套接字对象的内部表示中,并在对select(2)and的调用中使用它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;

至于原来的问题...

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

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

于 2013-04-25T13:06:35.970 回答
1

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

于 2013-04-25T22:31:20.773 回答