我有以下代码:
use IO::Socket::INET;
use Sys::Hostname;
use Socket;
my($addr)=inet_ntoa((gethostbyname(hostname))[4]);
my $port_to_use = 7777;
my $socket = new IO::Socket::INET (
LocalHost => $addr,
LocalPort => $port_to_use,
Proto => 'tcp',
Listen => 5,
Reuse => 1
);
die "cannot create socket $!\n" unless $socket;
my $client_socket = $socket->accept();
如果我在一个屏幕上启动它并在另一个屏幕中启动另一个屏幕,我会收到一个错误:
cannot create socket Address already in use
而不是死亡,我想尝试使用不同的端口(递增1),直到它找到要使用的端口。
我尝试将die
行转换为eval
,但我无法抓住它
有什么建议吗?
答案 0 :(得分:4)
使用循环:
use IO::Socket::INET;
use Sys::Hostname;
use Socket;
my($addr)=inet_ntoa((gethostbyname(hostname))[4]);
my $port_to_use = 7776;
my $fail =1;
my $socket;
while ($fail == 1){
$port_to_use++;
$fail = 0;
warn $port_to_use;
$socket = IO::Socket::INET->new (
LocalHost => $addr,
LocalPort => $port_to_use,
Proto => 'tcp',
Listen => 5,
Reuse => 0
) or $fail =1;
}
warn $socket->accept();
答案 1 :(得分:3)
这是一个更整洁的替代方案,它实际上会检查以确保绑定到给定端口的失败是由于端口正在使用。它还限制要检查的端口范围。如果您使用代码in the other answer,并且,如果由于某种原因,机器不允许您的应用程序绑定到任何端口,您将陷入无限循环。它还可能导致您的应用程序绑定到本来应该保留的端口等。
#!/usr/bin/env perl
use strict;
use warnings;
use Carp qw( croak );
use Errno qw( EADDRINUSE );
use IO::Socket::INET;
use Sys::Hostname qw( hostname );
use Socket;
# These can come from a config file or command line
# See also https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Dynamic.2C_private_or_ephemeral_ports
# https://unix.stackexchange.com/a/39784/2371
my @port_range = (0xC000, 0xFFFF);
my $addr = inet_ntoa( (gethostbyname(hostname) )[4]);
my $socket;
TRY_PORT:
for my $port ($port_range[0] .. $port_range[1]) {
warn "Trying port $port\n";
$socket = IO::Socket::INET->new(
LocalHost => $addr,
LocalPort => $port,
Proto => 'tcp',
Listen => 7,
Reuse => 0,
);
if ($socket) {
warn "Bound to port $port\n";
last TRY_PORT;
}
if ( EADDRINUSE != $! ) {
croak "Cannot bind to port '$port': $!";
}
warn "Port in use, trying the next one\n";
}
$socket->accept
or croak "...";
# ...