48

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

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

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

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

4

3 に答える 3

38

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

なし。

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

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

新しいクライアントを受け入れるスレッドが への呼び出しで喜んでブロックするaccept()場合は、そこでも問題ありません。

それでも、TCP サーバーには、心に留めておきたい微妙な問題が 1 つあります... プログラムが成長して複数のクライアントを処理し、定期的なハウスキーピングを行う必要がある場合。selectタイムアウト付きのステートメントを使用して、リスニング ソケット (クライアント接続の試行を示し、次に接続) の可読性をチェックするのは自然で魅力的acceptです。そこには競合状態があります: クライアント接続の試行が と の間でドロップした可能性がselect()ありaccept()ますaccept()select()クライアントが接続します。

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

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

于 2012-10-23T05:01:54.150 に答える
26

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

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

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

于 2014-02-15T19:12:17.583 に答える
25

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

于 2012-10-23T00:11:26.073 に答える