【问题标题】:Socket creation fails after many successful attempts多次成功尝试后创建套接字失败
【发布时间】:2015-10-14 01:07:57
【问题描述】:

我在“localhost”上使用客户端/服务器连接,服务器用 Python 编写,客户端用 Perl 编写。

每次(Perl)客户端向服务器传输数据时,我当前都会使用以下行创建一个新套接字:

my $socket = new IO::Socket::INET ( PeerHost => inet_ntoa($self->{server}),
                                    PeerPort => $self->{port},  Proto => 'tcp' );

然后我使用 send 方法发送数据并使用选项 1(完成写入)调用 shutdown。然后我收到带有 recv 方法的响应,并使用选项 2 调用关闭(完成阅读)。然后我在套接字上调用 close 。在 Perl 中是这样写的:

$socket->send($record);
shutdown($socket, 1);
my $response = "";
$socket->recv($response, BUF_SIZE);
shutdown($socket, 0);
$socket->close();

由于我的套接字存储在一个局部变量中,我希望它在我离开我的发送函数后得到垃圾收集。但是,每次我创建一个新套接字时,内存占用都会增加几千字节。

然后,经过数千次调用,新套接字的创建失败。如果我然后等待几秒钟再试一次,它通常会创建好,尽管在此期间进程的内存占用没有改变。

有人能告诉我这种奇怪行为的原因,甚至是避免它的解决方案吗?

只是为了完成 - 这是在 Python 中创建服务器套接字的方式:

comm_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comm_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
comm_socket.bind((TCP_IP, TCP_PORT))
comm_socket.listen(1)

【问题讨论】:

  • 您是否在测试您的关闭/关机等是否确实有效,当它出现异常时,“netstat -a”会告诉您什么?因为这听起来像是打开套接字过多的问题。
  • 你告诉我们。检查每个套接字函数调用的返回值和$!
  • 我同意 Sobrique 的观点;我不知道你在做什么是否允许这样做,但如果可能的话,我建议重构你的实现以尽可能重用套接字
  • 感谢您这么快回答!套接字上的任何函数调用都不会标记错误。仅当创建新套接字失败时,我才得到“每个套接字地址(协议/网络地址/端口)通常只允许使用一次。”这个问题经常出现几秒;然后一切都继续正常工作几分钟,直到问题再次出现(同样只有几秒钟)。当问题出现时,我等待 1..3 秒,然后重试创建套接字,直到最终成功。
  • 大卫:“你为什么这样做?”是什么意思。您的意思是一直重新创建套接字吗?如果是这样:我不知道,如何重新使用它。你能告诉我吗?

标签: python perl sockets


【解决方案1】:

我现在知道了,会发生什么:来自 Sobrique 的提示是必不可少的。在我运行我的程序之前,我用“netstat -a”检查了情况,当它运行时。

似乎我创建的每个套接字都会在那里停留几分钟,即使它已被 Perl 关闭。连接保持在状态 TIME_WAIT 的列表中。如果我在比等待时间更短的时间内创建和销毁套接字数千次,那么系统会耗尽临时端口(这是创建时自动分配给客户端套接字的端口号;从 0xC000 = 49152 到 0xFFFF = 65535 左右)。在 49152 被清理之前达到 65535 时,不能创建新的套接字。一段时间后,系统会清理一些连接,从而释放一些短暂的端口号,然后可以再次创建新的套接字。

现在我发现了几篇文章,介绍了如何缩短等待时间,这将使内核更快地清理列表,而我的应用程序将不再足够快而导致系统超载。

但是我没有在我的系统上找到注册表项。也许我必须进入管理员模式 - 但这是另一个应该更容易解决的问题......

感谢您的帮助!

【讨论】:

  • 嗨 - 我仍然无法让它工作。更改超时无论如何都不是最好的解决方案。虽然我设置了 SO_REUSEADDR 标志,但连接没有被重用。我也在客户端尝试过(这可能会告诉你,我真的不知道,当客户端和服务器之间建立连接时到底发生了什么)。我现在已经阅读了很多教程,但它们都只处理这些一次性客户端。我从来没有找到任何例子来展示如何实现一个不断重新连接的客户端。
猜你喜欢
  • 2018-03-16
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多