2013-04-25 119 views
1

我找不到任何这文件除了从一些Python documentation为什么SO_RCVTIMEO从侦听套接字继承到接受的套接字?

18.1.4.2。超时和接受方法

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

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

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

我看过这个[question]:Are socket options inherited across accept() from the listening socket?,我觉得最后的判决仍然是执行定义的。我猜测在平台上比从每个内核读取源代码要容易。

这里它清楚地表明超时选项被继承。但在接受(2)的手册中,没有提到这一点。当我在我的一个盒子(嵌入式Linux盒子)上调试了一些C++代码时,我发现这非常令人震惊。我预计接受的套接字不会继承此选项。

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

回答

2

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

  1. 从来没有明确提及SO_RCVTIMEO选项
  2. 从来不说的超时值从监听套接字继承的,而是从全局超时值通过setdefaulttimeout()

看着为socketmodule.c的源代码中设置,巨蟒甚至不使用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没有在其上它的编译平台上定义的。由accept()方法返回

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

...插座继承超时...

...那是因为Python的内部实现accept()明确设置新的插座上线732默认的超时值的内部超时值...

s->sock_timeout = defaulttimeout; 

至于原来的问题。 ...

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

...我想你必须通过内核源代码,直到你找到它打猎,但它可能是简单的只是为了让没有什么是继承的假设,并明确覆盖你从任何改变他们的选择默认位于由accept(2)返回的新套接字FD上的父套接字FD上。

+0

我明白了。所以Python实际上强制执行此行为,而不是accept()本身。我正在阅读Linux内核代码,接受()[link](http://lxr.linux.no/#linux+v3.8.8/net/tipc/socket.c#L1510)的实现,到目前为止真的很困惑。 – 2013-04-26 03:12:28

+0

@WangWei看起来我把原来的问题误解为Python问题而不是C问题。查看更新的答案。 – Aya 2013-04-26 09:03:11

+0

谢谢。这是一个非常有见地的答案。 – 2013-04-27 08:00:20

1

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

+0

看起来它确实是一个与内核相关的行为。我想这有点像C++语言中的“实现定义”。 – 2013-04-26 03:13:48