[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 メーリングリストの案内