• 締切済み

タイムアウト時ソケット通信を中断して次の処理を実行したい

だいぶはしょってありますが、大雑把な流れは下のようなサブルーチンです。 タイムアウト時エラーメッセージに飛んでしまうと、その後の&kaiseki_beta;が実行されません。 タイムアウト時にソケット通信を中断して、その後の処理を実行させたいのですが、方法がわかりません。 $SIG{'ALRM'} = \&closeSocket(SOCK);とかやってみたのですが、500エラーになってしまい困っています。 何か良い方法があったら教えてください。 sub autobeta { $SIG{'ALRM'} = \&TimeoutError; eval { alarm 10; }; if (&openSocket(SOCK, $url, $method, \%header, $stdin)) { $vieweron = 0; open(DATA,">$betafile"); while(<SOCK>) { if ($vieweron == 1) { print DATA $_; } if ($vieweron == 2) { $vieweron = 1; } if ($_ =~ /Content-Type/i) { $vieweron = 2; } } close(DATA); &closeSocket(SOCK); } else { &error; } eval { alarm 0; }; &kaiseki_beta; return($beta); }

  • Perl
  • 回答数2
  • ありがとう数2

みんなの回答

  • guci-ok
  • ベストアンサー率33% (49/146)
回答No.2

Webのアクセスは、LWPで簡単にできますから、生でゴリゴリ書きすぎないように して下さい。 ソケットを直に扱う場合は、 use IO::Socket; use IO::Select; してプログラムします。 my $readers = IO::Select->new(); $readers->add($sock); my @ready = $readers->can_read($timeOutSec); if (@ready) { # 読込み... } else { # タイムアウト発生 }

perl2006
質問者

お礼

LWPですか? 勉強不足でまったく知りませんでした。 もう一度調べてみます。 回答ありがとうございました。

  • galluda
  • ベストアンサー率35% (440/1242)
回答No.1

がると申します。 ソケット通信のタイムアウトを捕捉するのであれば、select関数というものがあります。 http://flex.ee.uec.ac.jp/texi/perl/perl_68.html http://hp.vector.co.jp/authors/VA003991/kouza/senior/kouza_socker_perl.html このあたりで如何でしょうか?

perl2006
質問者

お礼

select関数でデータが来ているかどうかを確認してどうにかする、っていうことですね。 何か使えそうな気がしますが・・・ 考えてみます。 回答ありがとうございました。

関連するQ&A

  • alarmのタイムアウト後の処理でスクリプトを止めない方法をご教授ください

    はじめまして。 現在perlで簡単なRSSリーダーを作っています。 簡単に書けば下記のようなスクリプトです。 use LWP::Simple; use XML::RSS; foreach(@hoge) { # @hogeはrssファイルのURL $SIG{ALRM} = sub{ die("alarm_error"); }; alarm 10; $rss->parse($_); alarm 0; } rssファイルをとりにいって10秒たって取得できなければnextで次のrssファイルへという形にしたいのですがどうもやり方がわかりません。 いろんなところで調べてもタイムアウト後はdie等によって強制終了するやり方しか見つかりませんでした。 タイムアウト後nextを使えるやり方をご存知のかたおられたらお教えください。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • タイムアウト

    SQLServer2008Exを使用してます。 MSSMSでクエリ(SELECT文)を実行するとタイムアウトになってしまします。 データの量はそれなりにあるのですが、実行タイムアウトは0(ゼロ)無限の待ち時間に設定してあるのに何故なんでしょうか?

  • Linux C言語 ソケット通信について

    C言語でソケット通信のプログラムを始めて作成しました。 受信時のデータ量が少ない場合は問題ないのですが、データ量が多くなると、 サーバーの受信が、出来たり、出来なかったりと不安定になります。 ログを確認しますと、パケットが勝手に分割されサーバーで受信した場合に、 おかしな動きになることがわかりました。 なぜそのようになるのか、また何がいけないのかわかりません。 どうぞご教授をお願いします。 FD_ZERO(&r_socket); FD_SET(sock, &r_socket); width = sock+1; *leng = 0; ef = TRUE; memset(&s,0x00,sizeof(s)); /* タイムアウト設定 */ time.tv_sec = 3; time.tv_usec = 0; while(1) { /* 受信待機 */ ret = select(width, &r_socket, NULL, NULL, &time) if ( ret < 0 ) { "受信待機エラー"表示 break; } if ( ret = 0 ) { "タイムアウトエラー"表示 break; } /* パケットを受信 */ if ( FD_ISSET(sock, &r_socket)) { memset(&rb,0x00,sizeof(rb)); read_len = read(sock, rb, sizeof(rb)); "受信した内容をログに出力" /* 割り込み中断エラーは継続し、その他エラーは終了する */ if ( read_len < 0 ) { if ( errno == EINTR ) { continue; } else { ef = FALSE; "受信エラー"表示 break; } } /* クライアントのソケットが閉じた場合は終了する */ if ( read_len == 0 ) { break; } /* データ送信要求を受信した場合は終了する */ if ( rb[read_len-1] == ACK ) { break; } /* 受信バッファーへ取り込み */ if ( rb[read_len-1] == ETX || rb[read_len-1] == ETB ) { len = read_len - 1; } else { len = read_len; } for (i = 0;i < len;i++) { if ( rb[i] != ETB ) { rsbuf[(*leng)++] = rb[i]; } } /* 最終データ時は終了する */ if ( rb[read_len-1] == ETX ) { break; } /* 最終データでない場合はデータ送信要求を送信する */ if ( rb[read_len-1] == ETB ) { sprintf(trxmsg,"%1c",ACK); ef = send_socket(sock, strlen(trxmsg), trxmsg); if ( ef != TRUE ) { break; } } } }

  • Windowsで重い処理を実行したい

    CGIを作成している環境が Windows2000+IIS+ActivePerlで、時間がかかる処理を 行うプログラムを作成しています。 いろいろ調べて、alarm()とシグナルでブラウザタイムアウトを 防ぐ方法や、forkして子プロセスする方法などを、 試したのですが、うまくいかず、 よくよく調べてみるとWindows環境だと、alarmもforkも未実装らしく困り果てています。 IISでタイムアウト時間を延ばすのは避けたいです。 ブラウザのタイムアウトを回避しつつ、処理の長い CGIを実行するいい方法はないでしょうか?

    • ベストアンサー
    • Perl
  • acceptをalarmでタイムアウトさせる処理がうまくいきません

    お世話になります。 C言語でソケット通信でサーバ側のaccept処理のブロック状態を alarm関数で事前にタイムアウトする秒数を設定しておき、割り込みをおこさせて割り込み処理後、再開した際にaccept関数がエラーを返しerrnoにEINTRが返ってきているかを判断してタイムアウト処理を行うという目的で以下のソースを作成しました。 しかし、実際に動作させてみるとalarmが呼び出されシグナルハンドラとして設定しているsigcatch関数が呼び出され、標準出力にsigcatch関数中で出力しているメッセージが出力されますが、そのままブロック状態から変化しませんでした。 ソケットのクライアントプログラムを接続したところ、acceptが成功して接続が確立されました。 この方式による実現が可能かどうか、不可能であれば代替方法を教えていただきたいと考えております。 お手数おかけしますが、ご回答のほどよろしくお願いします。 コンパイルおよび実行環境は以下となっています。 Red Hat Enterprise Linux ES release 4 (Nahant Update 3) Kernel 2.6.9-34.ELsmp on an i686 glibc-2.3.4-2.19 ###################以下、C言語のソースです##################### #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <signal.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <stdlib.h> #define BUFFER_SIZE 256 void sigcatch(int); int main() { unsigned short port = 9876; int srcSocket; int dstSocket; struct sigaction sa_sigint; struct sockaddr_in srcAddr; struct sockaddr_in dstAddr; int dstAddrSize = sizeof(dstAddr); int numrcv; char buffer[BUFFER_SIZE]; int status = 0; int select_cnt = 0; fd_set readfds; int n; struct timeval timeout; int re; char *toSendText = "This is a test"; memset(&srcAddr, 0, sizeof(srcAddr)); srcAddr.sin_port = htons(port); srcAddr.sin_family = AF_INET; srcAddr.sin_addr.s_addr = htonl(INADDR_ANY); srcSocket = socket(AF_INET, SOCK_STREAM, 0); bind(srcSocket, (struct sockaddr *) &srcAddr, sizeof(srcAddr)); listen(srcSocket, 1); printf("Waiting for connection ...\n"); memset(&sa_sigint, 0, sizeof(sa_sigint)); sa_sigint.sa_handler = sigcatch; sa_sigint.sa_flags = SA_RESTART; if (sigaction(SIGALRM, &sa_sigint, NULL) < 0) { perror("sigaction"); exit(1); } alarm(10); dstSocket = accept(srcSocket, (struct sockaddr *) &dstAddr, &dstAddrSize); if ( dstSocket == -1 ){ if ( errno == EINTR ){ printf("accept timeout!\n"); }else{ printf("accept error![%d]\n",errno); } exit(-1); } signal( SIGALRM , SIG_IGN ); printf("Connected from %s\n", inet_ntoa(dstAddr.sin_addr)); while(1) { FD_ZERO( &readfds ); FD_SET( dstSocket , &readfds ); n = dstSocket + 1; timeout.tv_sec = 0; timeout.tv_usec = 0; re = select( n , &readfds , NULL , NULL , &timeout ); select_cnt++; if( re > 0 ){ printf("select count %d\n",select_cnt); if ( FD_ISSET( dstSocket , &readfds ) ){ numrcv = recv(dstSocket, buffer, BUFFER_SIZE, 0); if(numrcv == 0 || numrcv == -1) { status = close(dstSocket); break; } printf("received: %s\n", buffer); send(dstSocket, toSendText, strlen(toSendText)+1, 0); } } } } void sigcatch(int sig) { printf("catch signal %d\n", sig); if (sig == SIGALRM) { printf("catch SIGALRM and exit.\n"); } }

  • IISのタイムアウト設定について

    Windows2000+IIS6.0+ActivePerlで、時間がかかる処理を行うプログラムを作成しているのですが、 CGIタイムアウトが発生してしまい、最後まで実行 出来ません。 IISの設定で、ASPのタイムアウトや、セッションタイムアウトを30分とかに設定してもなぜか5分ほどでエラーになってしまいます。 どのようにすればCGIの実行時間を延ばせるのでしょうか?

  • PostgreSQLのタイムアウトについて

    VB.NETとPostgreSQLで社内システムを作っています。 更新クエリを実行すると15秒くらいでタイムアウトしてしまいます。 (エラーコードはメモを持ち帰るのを忘れたため覚えておりません…が、割と急いでいるので質問させて頂いてます) Statement_Timeoutはいじっておらず、値は0のままです。 プロバイダはnpgsqlです。 タイムアウトしないようにするにはどうすればいいでしょうか。 アドバイスお願いいたします。

  • VB.netで、シリアル通信のタイムアウト処理について

    VB.netで、シリアル通信のタイムアウト処理について http://msdn.microsoft.com/ja-jp/library/7ya7y41k.aspx このサイトのコードを、参考にしています。 ------------------------------------ここから Dim com1 As IO.Ports.SerialPort = Nothing Try com1 = My.Computer.Ports.OpenSerialPort("COM1") com1.ReadTimeout = 10000 Catch ex As TimeoutException returnStr = "Error: Serial Port read timed out." Finally If com1 IsNot Nothing Then com1.Close() End Try ------------------------------------ここまで この方法ですと、タイムアウトが発生したらポートを閉じるようですが、これを、送信したシリアルのデータを再度、送信させたいと思います。 そして、何度かリトライを掛けた後に、やっぱり駄目だったときに ポートを閉じたいと思います。 どんな方法がありますか? 参考になりそうなサイトなどがありましたら、教えていただけませんか。 以上、よろしくお願いします。

  • データ読込時のタイムアウト

    SQL-Serverのデータ(約30万件)を関数で処理した結果、約1000件くらいを、VS2005のレポートサービスで出力したいと思います。 その際、大体50:50の確立でタイムアウトを起こしてしまいます。 エラーを起こす場所は、 Me.××TableAdapter.Fill(Me.▲▲DataSet.××) です。 SQLコマンドに対しては、CommandTimeoutで対処するのは解りますが、テーブルアダプタを介してのデータの読込に関するタイムアウトの時間設定が解りません。どうしたらよろしいでしょうか?

  • デバイスタイムアウト

    ハードディスクドライブのデータを他のハードディスクドライブにコピー中に「○○○○:デバイスタイムアウト」「タイムアウト期間内に、指定した¥Device\Harddisc1\DR3 でのI/O操作が完了しませんでした。」「キャンセル・再実行(T)・続行(C)」というウィンドウ表示が出てしまいます。 ハードディスクドライブが、何か関係はあるのでしょうか? どうか対処方法を教えて下さい。 初心者ですのでどうぞよろしくお願いします

専門家に質問してみよう