totofugaのブログ

ネットワークとかc言語、perlの話。

サーバーで複数ポートを待ち受ける

socketは普通にacceptすると処理をblockしてしまうので複数のポートの待ちうけが出来ません。 acceptする前にIO->Selectのcan_readを使用することにより複数ポートの待ちうけが可能になります。

#!/usr/bin/perl                                      
use strict;                                          
use warnings;                                        
use IO::Socket;                                      
use IO::Select;                                      
                                                     
my @ports = (6000, 7000);                            
                                                     
my $select = IO::Select->new;                        
                                                     
foreach my $port ( @ports ) {                        
    my $listen = IO::Socket::INET->new(              
        Listen => SOMAXCONN,                         
        LocalPort => $port,                          
        Proto => 'tcp',                              
    ) or die $@;                                     
                                                     
    $select->add($listen);                           
}                                                    
                                                     
my @handles;                                         
while(@handles = $select->can_read) {                
    foreach my $handle (@handles) {                  
        my $new = $handle->accept();                 
        if ( my $pid = fork ) {                      
            $new->close();                           
        } else {                                     
                                                     
            select($new);                            
            print "connect to @{[$new->sockport]}\n";
            exit(0);                                 
        }                                            
    }                                                
}

telnetでアクセスすると6000と7000どちらのポートでもアクセスできることを確認できます。

$telnet localhost 6000
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
connect to 6000
Connection closed by foreign host.
$ telnet localhost 7000
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
connect to 7000
Connection closed by foreign host.