ファイヤープロジェクト
select
2003-07-20T15:13+09:00   matsu
selectを使用して複数のファイルディスクリプタからの入出力を制御
selectを使用すると,複数のファイルディスクリプタを監視し,変化があったファイルディスクリプタを処理することができる.また,タイムアウトを設定することもできる.この項ではPF_INET,SOCK_STREAMで作成したソケットと,stdinの状態をselectを使用して監視し,処理する.以下にその流れを示す.
サーバクライアント
socketsocket
bind
listen
selectconnect
accept
何かする何かする
closeclose
上はselectでソケットを監視する場合の例である.サーバのstdinとソケットを監視する場合,stdinは通常と同様に扱うことができる.
int select(int n,
           fd_set *readfds,
           fd_set *writefds,
           fd_set *exceptfds,
           struct timeval *timeout);
selectの引数には,fd_setというファイルディスクリプタの集合がある.そして監視する状態(読み込めるか,書き込めるか,エラー)によって,*readfds,*writefds,*exceptfdsを設定する.nは,これら三つのファイルディスクリプタ集合のうち,最大の「値」(個数ではない)+1を指定する.nの最大値はFD_SETSIZEである.fd_setはいくつかのマクロで設定,制御する.
FD_CLR(int fd, fd_set *set);
*setからfdを削除する.
FD_ISSET(int fd, fd_set *set);
*setにfdがセットされていれば1を返す.
FD_SET(int fd, fd_set *set);
*setにfdをセットする.
FD_ZERO(fd_set *set);
*setを空に初期化する.
selectが返ってくると,ファイルディスクリプタ集合には変化があったファイルディスクリプタのみが格納されている.また,タイムアウトにはtimeval構造体を使用する.以下のサンプルでは,サーバはselectでソケットとstdinを監視することによって,クライアントからの送信された文字列か,stdinから入力された文字列を出力する.また,タイムアウトも設定する.サーバのサンプルを以下に示す.
サーバではwhile(1)でstdinとソケットを監視し,入力があればそれを出力している.また,2秒でselectをタイムアウトしてTIMEOUTと出力し,またselectする.クライアントは特に目新しいことはない.
以下に実行結果を示す.まずサーバ.
$ ./server 127.0.0.1 9999

TIMEOUT

TIMEOUT
client-fuga
TIMEOUT
client-hoge
TIMEOUT
server
TIMEOUT
-hoge
server-hoge
ser
TIMEOUT
ver-fuga
server-fuga

TIMEOUT
exit
exit
そしてクライアント
$ ./client 127.0.0.1 9999 client-fuga
$ ./client 127.0.0.1 9999 client-hoge
サーバでは2秒でselectがタイムアウトしてTIMEOUTを出力する.そして2秒以内にソケットかstdinからの入力があればそれを出力する.上は
  1. サーバを起動
  2. クライアントを実行
  3. クライアントを実行
  4. サーバの標準入力
  5. サーバの標準入力
  6. サーバの標準入力(exit)
をした結果である.
matsu(C)
Since 2002
Mail to matsu