ITエンジニアの技術メモ

神奈川在住のITエンジニアの備忘録です。主にプログラミング(Perl, Java など)やネットワーク技術について、仕事などを通じて学んだことを自分の中で整理するためにゆるゆると書いています。誰かのご参考になれば幸いです。

tcp/udpポートを確保し続けるスクリプトを少しエンハンスした。

以前、tcp/udpポートを確保し続けるスクリプト holdPort.pl を作成した。
akrad.hatenablog.com


これに引数でholdするIPアドレスを指定できる機能を追加した。例えば、「perl holdPort.pl -port 8080 -ip 127.0.0.1」と実行すると、holdPort.pl は 127.0.0.1:8080/tcp をholdする。IPアドレスを指定しなければ、INADDR ANY (0.0.0.0) でholdする。

use strict;
use warnings;
use Socket;
use Getopt::Long 'GetOptions';

my $ip;
my $port;
my $udp;
GetOptions(
    'ip=s'   => \$ip,
    'port=i' => \$port,
    'udp'    => \$udp
);

my $sockAddr;
if ($ip) {
    my $packedIp = inet_aton($ip);
    $sockAddr = sockaddr_in($port, $packedIp);
}
else {
    $sockAddr = sockaddr_in($port, INADDR_ANY);
}

my $serverSock;

if ($udp) {
    #------------------
    # UDP
    #------------------
    socket($serverSock, PF_INET, SOCK_DGRAM, getprotobyname('udp'))
        or die "Cannot create socket: $!";
    bind($serverSock, $sockAddr) or die "Cannot bind $port: $!";
    
    while (1) {
        recv($serverSock, my $buf, 1024, 0) or die "Cannot recv: $!";
    }
}
else {
    #------------------
    # TCP
    #------------------
    socket($serverSock, PF_INET, SOCK_STREAM, getprotobyname('tcp'))
        or die "Cannot create socket: $!";
    bind($serverSock, $sockAddr) or die "Cannot bind $port: $!";
    listen($serverSock, SOMAXCONN) or die "Cannot listen: $!";

    my $clientSock;
    while (1) {
        accept($clientSock, $serverSock) or die "Cannot accept: $!";
    }
}


IPアドレスを指定できるようにしたのは、ポートを確保する際、IPアドレスまで一致していないと、このスクリプトの目的であるポート・バッティングを引き起こせないため。例えば、スクリプト127.0.0.1:8080 をholdしている状態で、別プロセスとしてスクリプトを実行して 0.0.0.0:8080 をholdしてもエラーにならない。逆も同様で、0.0.0.0:8080 をhold している状態で 127.0.0.1:8080 をholdしてもエラーにならない。Windows上で実機検証したらそうなった。なぜポート・バッティングにならないのか分かっていないので、今後調査する。