web-dev-qa-db-ja.com

CまたはC ++の同じソケットで同時に読み取りと書き込みを行う

単一の接続を受け入れ、そのソケットを使用して読み取りスレッドと書き込みスレッドからメッセージを同時に読み書きする単純なサーバーを実装しています。 Linux上のc/c ++で同じソケット記述子から同時に読み書きするための安全で簡単な方法は何ですか?同じソケットからの複数のスレッドの読み取りと書き込みについて心配する必要はありません。1つの専用読み取りスレッドと1つの専用書き込みスレッドがソケットに書き込むからです。

上記のシナリオでは、何らかのロックが必要ですか?

上記のシナリオでは、ノンブロッキングソケットが必要ですか?

上記のシナリオで役立つオープンソースライブラリはありますか?

34
Jimm

上記のシナリオでは、何らかのロックが必要ですか?

なし。

上記のシナリオでは、ノンブロッキングソケットが必要ですか?

おそらく心配しているビット-確立された接続の読み取りおよび書き込みスレッド-スレッドがそこに座って完了するのを待っていれば、非ブロッキングである必要はありません。それは通常、選択またはポーリングまたは非同期操作ではなくスレッドを使用する理由の1つです。コードもシンプルに保ちます。

新しいクライアントを受け入れるスレッドがaccept()の呼び出しをブロックしても問題ない場合は、そこでも大丈夫です。

それでも、TCPサーバーを念頭に置いておくとよいかもしれません...複数のクライアントを処理するためにプログラムが成長し、定期的なハウスキーピングが必要な場合は、サーバーに微妙な問題があります。 selectステートメントをタイムアウト付きで使用して、リスニングソケットの読み取り可能性を確認しようとします-これはクライアント接続の試行を示します-そしてaccept接続があります。そこには競合状態があります:クライアント接続試行がselect()accept()の間でドロップされた可能性があります。その場合、accept()はリスニングソケットが非ブロッキングでない場合にブロックし、タイムリーな戻りを防ぐことができますselect()ループを実行し、別のクライアントが接続するまで定期的なタイムアウト処理を停止します。

上記のシナリオで役立つオープンソースライブラリはありますか?

基本的なサーバーを作成するためのライブラリは数百ありますが、最終的には、OSが提供するBSDソケットまたはWindowsのろくでなしで簡単に達成できます。

30
Tony Delroy

ソケットは双方向です。イーサネットまたはシリアルケーブルを実際に解剖したり、それらの低レベルのハードウェア配線図を見たりした場合、実際には「TX」(送信)および「RX」(受信)ラインの個別の銅線を見ることができます。デバイスコントローラーから「ソケット」のほとんどのOS APIまで信号を送信するソフトウェアはこれを反映しており、ほとんどのシステム(Linuxなど)でのソケットと通常のパイプの重要な違いです。

ソケットを最大限に活用するには、次のものが必要です。
1)非同期IO IO完了ポート、epoll()、または類似の非同期コールバックまたはイベントシステムを使用して起動するサポート) 'ソケットにデータが入ったときはいつでも、これは最低レベルの' ReadData 'APIを呼び出して、ソケット接続からメッセージを読み取る必要があります。
2)低レベルの書き込みをサポートする2番目のAPI。ソケットにバイトをプッシュし、 'ReadData'ロジックに必要なものに依存しない 'WriteData'(送信)。送信と受信はハードウェアレベルでも独立しているため、このレベルでロックやその他の同期を導入しないでください。
3)Socket IOスレッド)のプール。ソケットから読み取られる、またはソケットに書き込まれるデータの処理を盲目的に行います。
4)PROTOCOL CALLBACK:ソケットスレッドがスマートポインターを持っているコールバックオブジェクト。データブロブを解析して実際のHTTPリクエストに変換するなど、基本的なソケット接続の上にあるすべてのプロトコルレイヤーを処理します。ソケットはコンピューター間の単なるデータパイプであり、ソケットを介して送信されるデータは多くの場合、一連のフラグメント(パケット)として到着します。 UDPのようなプロトコルでは、パケットは順番が揃っていません。低レベルの「ReadData」と「WriteData」は、コンテンツ認識データ処理が実際に開始される場所であるため、スレッドからここにコールバックします。
5)プロトコルハンドラー自体が必要とするコールバック。 HTTPの場合、生のリクエストバッファをNiceオブジェクトにパッケージ化し、実際のサーブレットに渡すと、HTTP仕様に準拠した応答にシリアル化できるNice応答オブジェクトが返されます。

基本パターンに注意してください:双方向async IOソケットを完全に活用したい場合、システム全体を基本的に非同期(「コールバックのオニオン」)にする必要があります。ソケットの読み取りと書き込みを同時に行う方法はスレッドを使用するため、「ライター」スレッドと「リーダー」スレッド間で同期をとることができますが、プロトコルまたはその他の考慮事項が私の手を強制した場合にのみ行います。高度な非同期処理を使用してソケットで優れたパフォーマンスを得ることができるということは、そのようなシステムを堅牢な方法で構築することは重大な努力であることです。

18
Zack Yezek

心配する必要はありません。 1つのスレッドの読み取りと1つのスレッドの書き込みが期待どおりに機能します。ソケットは全二重なので、書き込み中に読み取ることができ、その逆も可能です。複数のライターがいる場合は心配する必要がありますが、そうではありません。

15
mfontanini