2016-07-27 40 views
4

Ich habe den folgenden Code:perl-Buchse: Zuwachs Port, wenn im Einsatz

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(); 

, wenn ich dies in einem Bildschirm starten und ein anderes in dem anderen Bildschirm starten, erhalte ich eine Fehlermeldung:

cannot create socket Address already in use 

Anstatt zu sterben, würde ich gerne versuchen, einen anderen Port zu verwenden (um 1 zu erhöhen), bis er den zu verwendenden Port findet.

Ich habe versuchen, die die Linie mit eval zu konvertieren, aber ich bin nicht in der Lage es

irgendwelche Vorschläge zu fangen?

Antwort

3

Hier ist eine aufgeräumter Alternative, die tatsächlich überprüft, um sicherzustellen, dass der Fehler an einen bestimmten Port zu binden, zum Hafen zurückzuführen war im Einsatz zu sein. Es begrenzt auch den zu überprüfenden Portbereich. Wenn Sie den Code in the other answer verwenden und wenn die Maschine aus irgendeinem Grund nicht zulässt, dass Ihre Anwendung an Ports gebunden wird, werden Sie in einer Endlosschleife stecken bleiben. Es kann auch Ihre Anwendung dazu führen, Ports zu binden, die ansonsten gelassen wurden allein sollte usw.

#!/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 "..."; 
# ... 
+1

danke das funktioniert super – ealeon

+0

Das wird nützlich sein, danke! Ich finde keine Ressource für verschiedene solche Fehlertypen. (Wenn sie in 'Errno' sind, sehe ich keine.) Würdest du eine Referenz dafür wissen? – zdim

+0

Siehe https://stackoverflow.com/q/172199/100754. –

4

Verwenden Sie einen Loop:

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(); 
+0

Erste Arbeiten Bildschirm, aber auf dem zweiten Bildschirm, im immer der Fehler auf einem undefinierten „-Methode nicht aufrufen können‚akzeptieren‘ Wert bei perl_server.pl Zeile 39 "das ist die Zeile" socket-> accept() "; – ealeon

+0

aber warum würde es aus "außer" ausbrechen, wenn $ socket nicht definiert ist? – ealeon

+0

ich denke, dass derjenige, den Sie ursprünglich hatten, richtiger war. aber aus irgendeinem Grund hat der zweite Bildschirm Probleme. Könntest du versuchen, dich selbst zu codieren und zu sehen, ob du den Fehler bekommst? – ealeon