1

複数のスレッドを持つアプリケーションがあり、1 つのスレッドが 4 つの tcp 接続を作成しています。このスレッドは、ポーリングなどを使用してこれら 4 つの接続の受信機能を処理する別のスレッドを作成し、元のスレッド (最初のスレッド) がメッセージの送信を開始します。これらの 4 つの接続 (ラウンド ロビン) に。以下の疑似コードのようなものです。

main()
{

    pthread_create( &thread1, NULL, sending_thread, (void*) args);

}

void *sending_thread( void *ptr )
{
    int i=0;
    int *connections;
    connections = create_connections();

    pthread_create( &thread1, NULL, receiving_thread, (void*)&connections);
        while(1) {

        send(connections[i], "test"); 
        i++;
        if (i > 3)
        i=0;             

        }
}

void *receiving_thread( void *ptr )
{
    char *msg; 
        msg = receive(connections[i]);
        save_received_msg_to_disk(msg);

}

私の質問は、接続を確認して切断されたものを起動するにはどうすればよいですか? たとえば、connection1 がダウンしたとします。同じ fd (この場合は connection[1]) で別の接続を作成する必要がありますか? または、このケースを処理する他の方法はありますか?

環境は Linux の C/pthread です

4

1 に答える 1

1

コードとコメントに基づくいくつかのポイントを次に示します。

  • スレッドはいくつかのことを並行して行うことを可能にしますが、常に同期に帰着するより複雑な設計に関しては、通常、コストはゼロではありません。あなたの場合のように、接続の1つを再確立して2つのスレッド間で再び共有する簡単な方法はありません。
  • 入力ストリームと出力ストリームが完全に独立しているアプリは見たことがありません。トンネリング プロキシや TCP ベースの VPN のようなものが理にかなっていると想像できますが、一般的に、一部の上位レベルのプロトコルは、送信スレッドと受信スレッドの間で再び仲裁を課す/必要とする要求応答セマンティクスを課します。
  • スループットが必要な場合と、レイテンシーを最小限に抑えようとする場合は状況が異なります。ミューテックスでのスリープ待機は、通常、前者には問題ありませんが、後者にはめったに良い考えではありません。単一のスレッドから複数のブロッキング ソケットへのラウンド ロビン書き込みは、両方に悪影響を及ぼします。
  • epoll(7)重い出力ストリームとまばらな入力がある場合、飽和した接続を検出し、それらが再び利用可能になったときに通知され、他の人を飢えさせるようなものを使用することだけが理にかなっています.

これがあなたの質問に直接答えないことは知っていますが、私の暴言リストはコメントに収まりませんでした。これが少し役立つことを願っています。

編集 0:

を使用した通常のセットアップは次のepoll(7)とおりです。

  • ソケットをノンブロッキングにします (fcntl(2)を使用O_NONBLOCK)。
  • 潜在的なチャネルごとにソケット記述子に設定epoll_data.fdします (この例では 4 つのソケット)。union epoll_dataソケット記述子だけよりも複雑な構造を維持したい場合は、他のオプションが可能です。
  • EPOLLINおよびを使用して、エッジ トリガーEPOLLET動作を取得します。つまり、入力バッファーが空でなくなったときにウェイクアップします。
  • からEPOLLOUT取得する場合にのみ設定し、それ以外の場合は通常どおり出力します。ここでは、出力バッファ スペースが利用可能になったことを検出するのと同じロジックです。EWOULDBLOCKwrite(2)EPOLLET
  • 相手側がきれいに切断されていることを検出するために使用します (突然の切断の場合は、エラー フォームEPOLLRDHUPを処理する必要があります)。EPIPEwrite(2)
  • epoll_wait(2)反復するイベントの数を返します。events & EPOLLIN入力 ( ) と出力 ( ) を別々にチェックしますevents & EPOLLOUT
  • data.fd取得するまで、(または関連付けられたソケットから) 読み取られた入力でEWOULDBLOCK
  • EWOULDBLOCK取得するか、保留中の出力データがなくなるまで、出力時に書き込みます(EPOLLOUTその場合は削除します)。

たくさんあるように見えますが、コツをつかめばとても簡単です。

non-blocking を実行することもできますconnect(2)。これは、壊れたストリームを再確立したい場合に、まだ動作している他のストリームに影響を与えない場合におそらく良い考えです ( set toでconnect(2)戻り-1、上記のようにソケットが書き込み可能になるのを待ちます)。errno(3)EINPROGRESS

于 2013-01-24T14:07:02.793 に答える