ソフトウェア設計及び演習2013
非同期通信とselect
複数の入力を扱う
あるいは,select (システムコール) の使い方
参考にするプログラム
serv.c service関数
service 関数の動き
サーバは,
-
一人のクライアントからのメッセージを画面に表示
- ソケット側のファイル識別子を read して,
- 標準出力のファイル識別子へ write.
- 自身のキーボードからの入力をクライアントへ送信
- 標準入力のファイル識別子を read して,
- ソケット側のファイル識別子へ write.
のどちらかを,行います.ただし,その順番を決めてしまった場合には, 入力データが届いていないファイル識別子を read しても read は待ち状態のままで,入力があるまで動き出しません.
待ちを生じさせないためには,入力データがあるかを確かめてから read する必要があります.それを行うのが select システムコールです.
このように入力データの到着順によって入力を行うことを, 非同期入力と呼びます.
service 関数の説明
struct fd_set
- 複数のファイル識別子の集合を表す構造体です.
struct fd_set mask, readfds;
- maskは入力を調べるファイル識別子集合
- readfds は入力データがあったファイル識別子集合
struct timeval timeout;
- 待ち合わせ時間設定用構造体
FD_ZERO(&mask);
- maskのファイル識別子集合を空にします.
FD_SET(0, &mask); /* stdin */ FD_SET(s, &mask); /* socket stream */
- 標準入力ファイル識別子をファイル識別子集合に加え
- socket側のファイル識別子もファイル識別子集合に加えます
timeout.tv_sec = 5; timeout.tv_usec = 0;
- timeval構造体に,5秒を設定します.入力がなかった場合のタイムアウト時間です.
if ((nfound = select (s+1, &readfds, 0, 0, &timeout)) == -1) { perror ("select failed"); }
selectの振舞
- 指定時間内にデータがこなければ,nfound の値を0にして,select は終了します.
- 指定時間内にデータがくれば,
- データがきた識別子番号を1にして,
- 来ていない識別子番号は0にして,
- nfound の値をデータがきたソケットの個数にする
- s+1 は,ファイル識別子集合の個数
- &readfds は,調べるファイル識別子集合を与えて,入力があったファイル識別子集合がセットされて返ってきます.
- select は,
- timeout時間内に,指定したファイル識別子集合に入力があった場合,そのファイル識別子集合をreadfds にセットして返します.select の戻り値は,入力のあったファイル識別子の個数です.
- timeout時間内に,入力がなかった場合は,タイムアウトとなり,select の戻り値は0がに返されます.
else if (nfound != 0) { if (FD_ISSET(0, &readfds)) { nw = read(0, buf, BUF_LEN); write(s, buf, nw); }; if (FD_ISSET(s, &readfds)) { nw = read(s, buf, BUF_LEN); write(1, buf, nw); }
- 0, s のファイル識別子から入力があったかを,FD_ISSETで調べます.
最終更新日:2013/11/19 10:25:33