FC2ブログ

select関数の使い方

socketからの接続や、データの受信を非同期に行うにはselectやepollを使いますが、
ここではselectについて使い方を説明します。

selectはまず、監視するファイルディスクリプタの集合を作成する必要があります。
それは

fd_set rfds;
FD_ZERO(&rfds);

のようにfd_setという型のデータを作成し、それをFD_ZEROで初期化します。
監視するデータは、read,write,exceptの3種類があるのですが、ここではreadだけを考えることにします。
このfd_set に監視するファイルディスクリプタをセットしますが、それは

FD_SET(listensock, &rfds);
FD_SET(sock1, &rfds);
FD_SET(sock2, &rfds);
・・・

のようにFD_SETを使ってセットします。

その後、

struct timeval timeout = { sec, usec };
int result = select(maxfd+1, &rfds, NULL, NULL, &timeout))

のようにして待ち受けます。
ここでsec秒とusecマイクロ秒待ち受けて何もイベントがない場合はタイムアウトとして0が戻ります。

さて、maxfdはFD_SETで監視する対象のファイルディスクリプタで、この場合は、
listensocket,sock1,socket2の中の最大のものになります。
多くのソースではselect()の最初の引数にFD_SETSIZEを指定しているものが多いですが、
FD_SETSIZEはfd_setの配列の数であってファイルディスクリプタの最大値ではないので
厳密には正しくないようですが、通常はファイルディスクリプタは0からFD_SETSIZEくらいの値になるので問題になることは少ないようです。

さて、selectで1以上の値が戻れば、応答できるファイルディスクリプタの個数がその値ということになります。
そしてそれはrfdsの中にセットされて戻ってくるので、

for (int i = 0; i <= maxfd; i++) {
if (!FD_ISSET(i, &rfds))
continue;
// ここにくるとファイルディスクリプタiについて処理ができる
if (i == listensocket) {
// accept処理
}
 else {
// read処理
}

という感じでひとつずつ調べることになります。

結局selectに渡すためのrfdsを毎回作成する必要があって、select内では渡されたファイルディスクリプタを全部調べることになり、その結果を呼び出しもとが、どのファイルディスクリプタがONになっているのかを渡したファイルディスクリプタについて全部スキャンして調べるということをしないといけないので、効率はよくない感じですね。

http://chattera.net/

スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

chattera.net

Author:chattera.net
フリーでソフト開発の仕事をしています。
自作したこのチャットシステムは、何か世の中に役に立つこともあるかと思いますので、お呼びがかかるとうれしいですね。

連絡先は chatteranet@gmail.com です。

また、ソフト開発関連のお誘いもうけたまわっております。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR