Perlでタイムアウト付きIOアクセスをするには

[上に] [前に] [次に]
Cz 1999/08/05(木) 21:00:42
Windows環境でのPerlでタイムアウト付きIOアクセスをする方法はないものでしょうか?。
たとえば、socketで、5秒のタイムアウト付きReadinをして、
メッセージがなければタイムアウトして他の処理へ、といった処理を、
fork無しでやりたいのですが。

ついでといってはなんですが、もう一つ。
windowsのtelnetやTeraTermで、telnet以外のポートを
叩いたときに、コネクトはするのですが、メッセージ表示も、
入力も受けつけなくなるのはどうしたら良いのでしょうか?。
Unixのtelnetからだと問題無いのですが・・・。

Cz 1999/08/05(木) 21:08:33
追加です。

具体的には、コンソール入力と、ソケットからのメッセージを、
fork無しでタイムシェアリングしながら監視するプログラムを
考えてます。

(それ以外でもタイムアウト付きアクセス使いたいのですが、とりあえず。)

B-Cus 1999/08/06(金) 18:11:29
> Windows環境でのPerlでタイムアウト付きIOアクセスをする方法はないものでしょうか?。
 eval {
  alarm(10);
  $buf=<SOCKET>;
  alarm(0);
 }
 if ( $@ =~ /タイムアウトが起こったかどうかわかるような文を書く/
  タイムアウトになった
 }
ただし Windows でできるかどうかは知りません。

> 具体的には、コンソール入力と、ソケットからのメッセージを、
より一般的には(4引数の方の)selectを使うと思います。

> windowsのtelnetやTeraTermで、telnet以外のポートを
これかな?
http://www.cs.gunma-u.ac.jp/~j5306050/net/win-telnet.html

B-Cus 1999/08/06(金) 18:20:39
う、抜けてた。
 $SIG{ALRM} = \&timed_out;
 sub timed_out {
  die 'TIMED OUT';
 }
 eval {
  alarm(10);
  $buf=<SOCKET>;
  alarm(0);
 }
 if ( $@ =~ /TIMED OUT/ ){
  タイムアウトになった
 }
ってことです。O'REILLY の「実用Perlプログラミング」って本に載ってます。

> http://www.cs.gunma-u.ac.jp/~j5306050/net/win-telnet.html
これ、記述内容に自信がないので(特にWindowsのとこ)、もし間違ってたら
教えてください。

ふじ 1999/08/06(金) 19:57:52
残念ながら・・・
> The Unsupported function alarm function is unimplemented
ということで。
Windows版の Perl には alarm 関数が実装されていないようです。
#NT4.0 SP3, Perl 5.005_03(ActivePerl Build 517) で確認。

代替手段があったら私も知りたい・・・

Cz 1999/08/06(金) 20:07:44
Telnetの件、参照先WWWページを見て解決しました。ありがとうございます!

さて、タイムアウト付きの方ですが・・・
SIGNAL自体が実装されていません :-)
引き続き情報お待ちしております。
(私自身もあっちこっち探している最中ですが)。

とほほ 1999/08/06(金) 23:30:01
B-Casさんの回答にもありましたが、タイムアウト処理は、引数が4つ
ある方のselect()を用いることで実現できると思います。

B-Cus 1999/08/07(土) 06:38:32
えっと、とほほさんには2・3回間違えられてるような気がしますが、
B-CasではなくB-Cusです :-)

B-Cus 1999/08/07(土) 07:02:27
4引数selectの使い方は、青ラクダ本にばっちり載ってます。
ところで、青ラクダ本のselectの項に、
 「この関数を使うとポーリングを避けることができる」
とありますが、一般的なポーリングってどうやるんですか?
fseekで最後に移動して、前回の場所と変わってたらその分を読む?
それとも lseek?

そもそも(ファイルディスクリプタ経由でアクセスできるとはいえ)、
socket に対してポーリングできるのかな?

B-Cus 1999/08/07(土) 10:09:16
> 一般的なポーリングってどうやるんですか?
ファイルに対しては、
 use FileHandle;
 $|=1;
 $fh = new FileHandle;
 $fh->open("./hoge");
 while (1){
  print <$fh>;
  $fh->clearerr;
 }
でいけるみたい。seekでもできそうな感じ。ソケットとの絡みは
よくわかりませんでした。

ちなみに4引数socketによるタイムアウトの使い方はここ。
http://www.kt.rim.or.jp/%7ekbk/perl5.005/perlipc.html#UDP_Message_Passing

ただし
 http://www.kt.rim.or.jp/%7ekbk/perl5.005/perlwin32.html#BUGS_AND_CAVEATS
  四引数の select() 呼び出しは、ソケットに関してのみサポートさ れています。
なので、STDINを監視するのは無理かもしれません。この際、Windowsなんて捨てちゃえ。

とほほ 1999/08/10(火) 11:28:32
> えっと、とほほさんには2・3回間違えられてるような気がしますが、
> B-CasではなくB-Cusです :-)
ごめんなさい。大変失礼を・・・(^^;)

> 一般的なポーリングってどうやるんですか?
UNIXのソケット関数だと、getsockopt()だかioctl()だかで、現在の
受信バッファ中のデータサイズを知ることができたので、これを定期
的にチェックする・・・ということかも・・・。

Cz 1999/08/17(火) 15:34:01
レス頂いた皆様、どうもありがとうございます。

さて、私は・・・・
結局、4変数のselectを使ってsoketをタイムアウト付き
アクセスし、コンソールに対して(win32では4変数socketは
未サポート)、タイムアウト付きアクセスできませんので、
ローカル(127.0.0.1)にループバックさせて、
2つのソケットに対してのタイムアウト付きアクセスで
解決させました。

個人的にはwindows環境捨てちゃえという意見、賛成なのですが :-P
今後も何か情報ありましたらお願いします。

Cz 1999/08/17(火) 15:35:10
訂正。

> win32では4変数socketは
win32では4変数selectは、

の間違いです。

[上に] [前に] [次に]