perl socket:如果在使用中增加端口

时间:2016-07-27 07:29:24

标签: perl sockets eval

我有以下代码:

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,但我无法抓住它

有什么建议吗?

2 个答案:

答案 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 "...";
# ...