2

解決方法がよくわからない問題があります。複数の接続を多重化するプログラムがあります。これらの接続は、ストリーミング データをすべて同時に受信しています。ストリームのビットレートが異なるため、ノンブロッキング ソケットを構成する必要がありました。私が実際に行ったことは、これらのソケットを配列内にループさせ、読み取るデータがあるかどうかを選択して検出し、そうでない場合は配列内の次の要素に進むことです。CPU が常に 100% であることを除けば、非常にうまく機能します。実際、ある時点でソケットから読み取るものが何もない場合でも、ループします。ソケットでデータが利用できないときはいつでもループをブロックし、データがあるときにループを続けることができるかどうかはよくわかりません。これが解決策かもしれないと思いますが、どうすればこれができるかわかりません。

どうもありがとうございました。

PS .: 参考までに、私はまだ学んでいるので、解決策が明らかであっても、私を責めないでください。


編集:

ここにいくつかの擬似コードがあります:

録画要求が来たら、新しい接続を作成してストリーム アドレスに接続します。成功した場合は、次の関数を使用して fdset をビルドします。

build_fdset()
{
    int ii;
    /* */
    FD_ZERO(&fdset);
    /* */
    for (ii = 0; ii < max; ii++)
    {
        if (astRecorder[ii].bUsed != FALSE && astRecorder[ii].socket != INVALID_SOCKET)
        {
            FD_SET(astRecorder[ii].socket,&fdset);
            /* */
            if (astRecorder[ii].socket > maxSocket)
                maxSocket = astRecorder[ii].socket;
        }
    }
}

次に、接続を処理するループ:

main_loop()
{
    struct timeval timeout;
    /* */
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    /* */
    for (;;)
    {   
        memcpy(&fdset_cpy,&fdset,sizeof(fdset));

        int ret = select((maxSocket + 1) , &fdset_cpy, NULL, NULL, &timeout);

        if (iSelectRet <= 0)
            continue;
        else
        {
            int ii;

            for(ii = 0; ii < max; ii++)
            {
                if ((recorders[ii].bUsed) && (FD_ISSET(recorders[ii].socket, &fdset_cpy)))
                {
                    /* receive from socket */
                    /* handle received data */
                }
            }
        }
    }
}

問題: タイムアウトを timeout.tv_sec = 1 timeout.tv_usec = 0 に設定すると、すべて正常に動作しますが、CPU 使用率が 100% になります! タイムアウトとして NULL を指定すると、ソケットにデータがあってもプログラムが select() でブロックされます。


解決:

さて、私はついにエラーを見つけました!上記のコードでは、メイン ループの前に 1 回だけタイムアウト値を設定しています。それに関する問題は、fdset に関しては、タイムアウト構造が select() 関数によって変更されることです。そのため、最初の正しいタイムアウト選択の後、タイムアウト構造は select() 関数によって変更され、0 に設定されます。これによりタイムアウトが 0 になるため、次にループが選択関数に到達したときにタイムアウトが発生するという問題が発生します。選択するのは0です!!!

助けようとした人たちに感謝します!私はそれを感謝します=)

4

2 に答える 2

4

select呼び出しのタイムアウトは、NULL永久に待機することを意味する場合があります。

于 2012-06-08T08:03:49.717 に答える
0

sleepすべてのストリームをチェックした後に使用して、ループの最後で CPU を放棄することもできます。このようにして、他のストリームにサービスを提供しないリスクを冒して、近い将来に受信データを取得するために単一のストリームに依存することはありません。

于 2012-06-08T10:47:56.310 に答える