• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:acceptをalarmでタイムアウトさせる処理がうまくいきません)

accept関数を使ったタイムアウト処理がうまくいかない

このQ&Aのポイント
  • C言語でソケット通信でサーバ側のaccept処理のブロック状態をalarm関数で事前にタイムアウトする秒数を設定しておき、割り込みをおこさせて割り込み処理後、再開した際にaccept関数がエラーを返しerrnoにEINTRが返ってきているかを判断してタイムアウト処理を行うという目的で以下のソースを作成しました。
  • しかし、実際に動作させてみるとalarmが呼び出されシグナルハンドラとして設定しているsigcatch関数が呼び出され、標準出力にsigcatch関数中で出力しているメッセージが出力されますが、そのままブロック状態から変化しませんでした。
  • ソケットのクライアントプログラムを接続したところ、acceptが成功して接続が確立されました。

質問者が選んだベストアンサー

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

要はacceptするときに、タイムアウトの監視もしたいということでしょうか。その場合は、alarmによる方法は採りません。 通常は、以下の方法を採ります。 acceptの前に、そのソケットに対し、selectを行います。その時、タイムアウト時間も指定します。selectから返るのは、acceptが出来る状態になったときか、selectがタイムアウトした場合の何れかです。

IamMasaki
質問者

お礼

行いたかったことはaccept時にタイムアウト監視をしたいということでした。 さっそくtatsu99さんの方法にて確認したところ無事タイムアウト監視ができるようになりました。ありがとうございます。 以下に修正ソースを記載します。 ###################以下、C言語のソースです##################### <宣言部元ソースと同じなので省略> //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"); FD_ZERO( &readfds ); FD_SET( srcSocket , &readfds ); n = srcSocket + 1; timeout.tv_sec = 10; timeout.tv_usec = 0; re = select( n , &readfds , NULL , NULL , &timeout ); if ( FD_ISSET( srcSocket , &readfds ) ){ dstSocket = accept(srcSocket, (struct sockaddr *) &dstAddr, &dstAddrSize); }else{ printf("accept timeout!\n"); exit(-1); } if ( dstSocket == -1 ){ printf("accept error![%d]\n",errno); exit(-1); } printf("Connected from %s\n", inet_ntoa(dstAddr.sin_addr)); <accept以後の処理元ソースと同じなので省略> <シグナルハンドラの関数は削除> //void sigcatch(int sig) { // printf("catch signal %d\n", sig); // if (sig == SIGALRM) { // printf("catch SIGALRM and exit.\n"); // } //}

その他の回答 (3)

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.4

シグナル動作は実行環境に依存するでしょうし動作も安全・確実とは限らないので、シグナル(システムの内部でシグナルを使って実装しているかどうか知らないが^^)を使わないで、やりたいことができるなら、シグナルを使わない select() や poll() を使う、tatsu99 さんの方法のほうがいいでしょうね^^

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.2

書き間違ってました^^『シグナルをキャッチしなければ』じゃなくて、キャッチするのはよくて、『sa_sigint.sa_flags = SA_RESTART;』を指定してるのが、リスタート指定なので、コメントアウトしたほうがいいと思います。『sa_sigint.sa_flags = SA_RESTART;』を無視するOSもあると思いますが、IamMasakiさんのOSはきちんとリスタートするんでしょう^^

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.1

シグナルをキャッチしていてデフォルト動作でない。IamMasakiさんのOSは、シグナルをキャッチして復帰したときに再実行という処理をするようになっているのではないですか?^^ シグナルをキャッチしなければ、意図通り動くのでは?

関連するQ&A