为啥 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_RCVTIMEOaccept(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设置超时

为啥在 useEffect 中侦听套接字事件时对服务器有多个请求?

C - 为啥我不能从本地主机外部访问我的服务器?

为啥套接字被阻止接收,而我睡在另一个线程上?

如何在 tcp 套接字侦听器中唯一标识套接字 id

接受侦听套接字上的侦听套接字上的连接(并且不再侦听)?