TCPサーバは、無事に終了できるのか [ColdFire V2]
付録基板同士のクライアント・サーバ・システムで作成したサーバは、最後に Listen ソケット(親ソケット、ルート・ソケット、何て呼べばいいんだ?)をクローズするようにはなっていましたが、無限ループでリクエストを待っているので事実上クローズはされていませんでした。 某所で、「Listen ソケットをクローズすると SilentC が沈黙する」との話題がありましたので、検証してみます。
停止機能付きサーバプログラム
今回作成したサーバ・プログラムは、TCPでリクエストを受け付けて、コネクション終了後に処理を行うインタプリタです。
main() { char *recv_buf; char listen,soc; long stat; recv_buf = MemoryAlloc(256); do { listen = CreateSocket(1); if (listen < 0) { PrStr("Failed to open LISTEN\r\n"); break; } PrStr("Listen socket=");PrNum(listen);PrStr("\r\n"); Bind(listen, 30049, 1); for (;;) { GetNetLine(0,0,0,0); soc = Accept(listen, -1); if (soc < 0) break; do { stat = GetNetLine(soc, recv_buf, 255, -1); if (stat < 0) { recv_buf[0] = '\0'; } } while (0); CloseSocket(soc); GetNetLine(0,0,0,1); if (StrStr(recv_buf, "hello") != 0) { PrStr("HELLO\r\n"); } else if (StrStr(recv_buf, "bye") != 0) { PrStr("BYE BYE\r\n"); break; } else { PrStr("What ?\r\n"); } } CloseSocket(listen); } while (0); MemoryFree(recv_buf); }
通信文に"hello"が含まれていたら"HELLO"とコンソールに表示し、"bye"が含まれていたら"BYE BYE"と表示しLISTENソケットを閉じます。 それ以外は"What ?"と表示します。 こういう構成なので、 telnet でお話できます。
telnetで話しかけたら
プログラムが準備できました。 ColdFire でプログラムを実行しておいて、telnetで"hello"を送信します。 続いて、"bye"を送信すると、
OK run Listen socket=4 HELLO BYE BYE
げっ、確かに沈黙してしまいました。
どこで止まっているのだろう
"CloseSocket(listen)"をコメントアウトすると、プログラム自体は正常に終了しますが、ソケットが閉じられていないので、?CreateSocket(0)と打ち込むと新しいソケットが割り当てられます。 また、再度実行すると沈黙してしまいます。 どうやら、CloseSocket関数で止まっているのは間違いなさそうです。
深追いしたところ、"LISTEN"状態からソケットを閉じる状態遷移が定義されていないように見えます。 "LISTEN"から"CLOSED"へのアーク(弧)が定義されていないので、ソケットを閉じるための条件である"FIN"の到着を待っているのだけどそんなものは来ない。 といった所でしょうか。
コンテストの〆切が間近なのに、解析作業ばっかりで、作品に取りかかれないよ。
参考文献
Interface (インターフェース) 2008年 09月号 [雑誌]
- 作者:
- 出版社/メーカー: CQ出版
- 発売日: 2008/07/25
- メディア: 雑誌
”某所”の中の人です。
検証ありがとうございます!
>Listenソケット
Winプログラムでは、よく「リッスンソケット」とかって言ってますね。
接続要求受付用の特別なソケットで、別コンピュータとの通信に使用しているソケットとは区別します。
>コンテスト〆切
げ、のんたんさん忙しかったんですね。。
突然お願いしちゃってすみませんでした。
てか、こんなのあったんだ。何か面白いのできたら応募してみようかな。。(←いつもどおり口だけ)
by yoneken (2008-10-18 14:28)