为啥 SO_RCVTIMEO 从侦听套接字继承到接受的套接字? [关闭]
Posted
技术标签:
【中文标题】为啥 SO_RCVTIMEO 从侦听套接字继承到接受的套接字? [关闭]【英文标题】:Why SO_RCVTIMEO is inherited from listening socket to accepted socket? [closed]为什么 SO_RCVTIMEO 从侦听套接字继承到接受的套接字? [关闭] 【发布时间】:2013-04-25 12:54:33 【问题描述】:除了一些 Python documentation 之外,我找不到任何关于此的文档
18.1.4.2。超时和接受方法
如果
getdefaulttimeout()
不是None
,则accept()
方法返回的套接字继承该超时。否则,行为取决于监听套接字的设置:如果监听套接字处于阻塞模式或超时模式,则
accept()
返回的套接字处于阻塞模式;如果监听套接字是非阻塞模式,
accept()
返回的套接字是阻塞还是非阻塞模式取决于操作系统。如果您想确保跨平台行为,建议您手动覆盖此设置。
我已经阅读了这个[问题]:Are socket options inherited across accept() from the listening socket?,我认为最终的判决仍然是实现定义的。我想在平台上进行测试比从每个内核读取源代码更容易。
这里清楚地说明了超时选项是继承的。但是在 accept(2) 的联机帮助页上,没有提到这一点。当我在我的一个盒子(嵌入式 Linux 盒子)上调试一些 C++ 代码时,我发现这非常令人震惊。我希望接受的套接字不会继承此选项。
我在哪里可以找到这个问题的明确答案?
【问题讨论】:
【参考方案1】:如果这是一个 C 问题,而不是 Python 问题,我不会根据 Python 文档得出关于 SO_RCVTIMEO
被 accept(2)
继承的任何结论。我想你可能还是误解了 Python 文档,因为它们......
-
永远不要明确提及
SO_RCVTIMEO
选项
永远不要说超时值是继承自监听socket,而是来自setdefaulttimeout()
设置的全局超时值
查看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。
【讨论】:
我明白了。因此 Python 实际上强制执行此行为,而不是 accept() 本身。我正在阅读accept()link实现的Linux内核代码,到目前为止真的很困惑。 @WangWei 看起来我将原始问题误解为 Python 问题而不是 C 问题。查看更新的答案。 谢谢。这是一个非常有见地的答案。【参考方案2】:BSD Sockets API 可以做到这一点。接受的套接字继承了侦听套接字的所有内容:接收缓冲区大小、超时、KEEPALIVE、close-on-exec。一些更高级别的 API(如 Java)会做更多的工作来撤销它,例如读取超时。
【讨论】:
看起来它确实是一个依赖于内核的行为。我想这有点像 C++ 语言中的“实现定义”。以上是关于为啥 SO_RCVTIMEO 从侦听套接字继承到接受的套接字? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
使用SO_RCVTIMEO套接字选项为recvfrom设置超时