我在" 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调用shutdown(完成读取)。然后我在套接字上调用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)
答案 0 :(得分:0)
我现在知道,会发生什么:来自Sobrique的暗示是必不可少的。我检查了" netstat -a"情况如何,在我运行我的程序之前,再次运行它。
看来我创建的每个套接字都会在那里停留几分钟,即使它已经被Perl关闭了。连接在状态TIME_WAIT中保留在列表中。如果我在比等待时间短的时间内创建并销毁套接字数千次,那么系统将耗尽临时端口(这是在创建时自动分配给客户端套接字的端口号;这从0xC000开始计数= 49152到0xFFFF = 65535左右)。在清除49152之前达到65535时,不能创建新的套接字。一段时间后,系统会清理一些连接,从而释放一些短暂的端口号,然后再次创建新的套接字。
现在我发现了几个帖子,告诉我们如何缩短等待时间,这会让内核更快地清理列表,而且我的应用程序不再足够快以超出系统。
但是我在我的系统上找不到注册表项。也许我必须进入管理模式 - 但这是另一个应该更容易解决的问题......
感谢您的帮助!