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