技術メモ

神奈川在住のITエンジニアの備忘録。おもにプログラミングやネットワーク技術について、学んだことを自分の中で整理するためにゆるゆると書いています。ちゃんと検証できていない部分もあるのでご参考程度となりますが、誰かのお役に立てれば幸いです。

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上で実機検証したらそうなった。なぜポート・バッティングにならないのか分かっていないので、今後調査する。