2021年12月22日

selectで複数のreadやrecvをキャッチする

selectで、例えばrs232Cの受信だったり、TCPの受信だったりをタイムアウト付きでチェックするときの定型として以下のように書くけど。

  int            fd;
    char          buf[];
    int             length;
    int             timeOutMs;
    fd_set        readfds ;
    struct        timeval tv;

    FD_ZERO( &readfds );
    FD_SET( fd, &readfds );
    tv.tv_sec = (int)(timeOutMs / 1000);
    tv.tv_usec = (int)((timeOutMs % 1000) * 1000);

    int  nfds = select( fd + 1, &readfds, NULL, NULL, &tv ) ;
    if( nfds == 0 )                                    // タイムアウト
        return( 0 ) ;

    return  read( fd, buf, length ) ;

これは1つのファイルディスクリプタの受信を待つ場合で。
複数だったらどーする?その分スレッドを立ち上げる?と疑問に思っていたが、
どうやらFD_SETを複数書けば良いみたいだ
    FD_SET( fd, &readfds );
    FD_SET( fd2, &readfds );
としてselect実行のあと、各ファイルディスクリプタに対して
  FD_ISSET( fd, &readfds ) != 0
  FD_ISSET( fd2, &readfds ) != 0
0以外となるもの(受信したファイルディスクリプタ)をそれぞれ調べ、あればreadだったりrecvだったりをぶちかますとよい様子。

注意として。
ファイルディスクリプタは1024個まで、らしい。
そもそも多い時はポーリングにした方が良いようですね。


なお。
Posixのメッセージはファイルディスクリプタではない→この方法が使えない。
Messageはシグナル通知(インターバルタイマーみたいに)することが可能とのこと。
便利なんか不便なんかようわからんな。
posted by すら at 17:47| プログラミングなこと