[Mew-dist 11471] alarm vs select
Kazu Yamamoto ( 山本和彦 )
kazu at example.com
1999年 11月 25日 (木) 20:34:39 JST
connect() 自身のタイムアウトが待てない場合は、alarm() を使うのではなく、
ソケットを non-blocking にしておいて、select() するのが一般的なようで
す。
motonori さんは、alarm が好きみたいですが、できれば non-blocking に書
き換えたいと思っています。でも、Windows できちんと動くのかとっても心配
です。
というわけで、Windows の人は、下記の test.pl を実行して下さい。
test.pl <hostname>
です。<hostname> には DNS には登録されているが、実際には存在しないホス
トを指定して下さい。そうしないと、connect() が刺さりません。そんなホス
トは近くにはないと言う人は、
test.pl kame203.kame.net
とやって下さい。
先頭の perl へのパスと、$timeout は適当に書き換えて下さい。
alarm() と select() の両方をテストします。
TEST for alarm
connecting ...
connecting ... done
INTERUPTED BY ALARM
TEST for fcntl
connecting as non-block
selecting ...
selecting ... done
SELECT TIMEOUT
となれば、成功です。上は、ブロックされた connect() を alarm() で抜けて
います。下は、non-blocking で connect() し、select() でブロックし、
select() のタイムアウトで抜けています。
全部大文字の行が出たら成功。いつまで経ってもでない、動かすとエラーにな
るなどは失敗です。デフォルトでは、それぞれ 2 秒ずつ待つので、5 秒ぐら
いで終了するはずです。
--かず
-------------- next part --------------
#! /usr/bin/perl
use POSIX;
use Socket;
use Fcntl;
$timeout = 2;
$commandname = $0;
die "$commandname <hostname>\n" if $#ARGV != 0;
$hostname = $ARGV[0];
($he_name, $he_alias, $he_type, $he_len, @he_addrs) = gethostbyname($hostname);
die "$hostname is not registered in DNS\n" if $he_name eq '';
die "$hostname doesn't have IP addresses.\n" if scalar(@he_addrs) == 0;
unless (socket(SOCK, AF_INET, SOCK_STREAM, 0)) {
die "can't open a socket\n";
}
### TEST for alarm
print "TEST for alarm\n";
$SIG{'ALRM'} = \&alarm_func;
foreach $he_addr (@he_addrs) {
$sin = pack_sockaddr_in(23, $he_addr);
print "connecting ...\n";
alarm($timeout);
connect(SOCK, $sin);
print "connecting ... done\n";
if ($! == EINTR) {
print "INTERUPTED BY ALARM\n";
} else {
print "connect succeeded\n";
}
}
close(SOCK);
### TEST for fcntl
print "\n";
print "TEST for fcntl\n";
unless (socket(SOCK, AF_INET, SOCK_STREAM, 0)) {
die "can't open a socket\n";
}
unless (fcntl(SOCK, &F_SETFL, O_NONBLOCK)) {
die "can't set as nonblock\n";
}
foreach $he_addr (@he_addrs) {
$sin = pack_sockaddr_in(23, $he_addr);
print "connecting as non-block \n";
connect(SOCK, $sin);
print "selecting ...\n";
$win = "";
vec($rin, fileno(SOCK), 1) = 1;
$nfound = select(undef, $wout=$win, undef, $timeout);
print "selecting ... done\n";
if ($nfound == 0) {
print "SELECT TIMEOUT\n";
} else {
print "connect succeeded\n";
}
}
sub alarm_func () {
}
Mew-dist メーリングリストの案内