同じソケットでsend / recvへの並列呼び出しは有効ですか?


127
  1. 同じソケットで、あるスレッドからsendを呼び出し、別のスレッドからrecvを呼び出すことはできますか?
  2. 同じソケットの異なるスレッドから複数の送信を並行して呼び出すことはできますか?

優れた設計ではこれを回避する必要があることはわかっていますが、これらのシステムAPIの動作は明確ではありません。私も同じことに関する良いドキュメントを見つけることができません。

方向へのポインタがあれば役立ちます。


3
なぜそうするのが悪い習慣だと主張するのですか?あなたが別のスレッドで聞いたり受け取ったりするので、それは私にはうまく見えます。
TheMathNoob 2017

回答:


92

POSIXはsend / recvをアトミック操作として定義しているため、POSIX send / recvについて話していると仮定すると、はい、複数のスレッドからそれらを同時に呼び出すことができ、動作します。

これは必ずしもそれらが並列に実行されることを意味するわけではありません。複数の送信の場合、2番目の送信は最初の送信が完了するまでブロックされる可能性があります。ソケットバッファーにデータを送信すると送信が完了するため、おそらくこれに気付かないでしょう。

SOCK_STREAMソケットを使用している場合、send / recvがメッセージの一部のみを送信または受信する可能性があるため、並列処理を行うことはあまり役に立ちません。つまり、処理が分割される可能性があります。

SOCK_STREAMソケットでのブロックの送信/受信は、少なくとも1バイトを送信または受信するまでブロックするだけなので、ブロックと非ブロックの違いは役に立ちません。


1
@Joao:SOCK_DGRAMソケットは「メッセージ境界の保持」として文書化されていますが、これはあまり明確ではありません。Linuxカーネルソースを見ると、少なくとも各送信と受信が単一のパケットをアトミックに処理していることがわかります(少なくともudpの場合)。
クリス・ドッド

2
@ケダー:どういう意味かわからない。sendすぐに戻って、データが送信バッファに置かれるように、データは非同期的にネットワークにnetowrkスタックを通って外に送出されます。したがって、1つのスレッドが送信し、1つのスレッドが受信している場合、受信スレッドが最初のパケットを受信する前に、送信スレッドが多くのパケットを送信する可能性があります。完全に非同期であり、同時ではありません。
Chris Dodd 2013年

6
@ChrisDodd、「POSIXはsend / recvをアトミック操作として定義する」へのリンクを提供できますか?
Suitianshi 2016

2
@suitianshi:POSIX 1003.1c標準ドキュメントには、再入可能(スレッドから呼び出すのに安全)であり、そうでない1003.1のすべての関数がリストされています。残念ながら、どこでも無料でオンラインで入手できることは知りません。
クリス・ドッド

2
私は上のコピーを発見した@ChrisDodd unix-systems.org/version4と私は章7.1でシステム・インタフェース表のリストを見ることができますが、それはアトミック操作としての機能を一覧表示する場所を確認しません。疑いの余地はありませんが、回答を共有/編集して、文書でのあなたの主張を正当化できますか?
user153882 2017

17

ソケット記述子は、特定のスレッドではなくプロセスに属しています。したがって、異なるスレッドの同じソケットとの間で送受信を行うことができ、OSが同期を処理します。

ただし、送信/受信の順序が意味的に重要である場合、あなた自身(それぞれのコード)は、スレッドの場合は常にそうであるように、異なるスレッドでの操作間の適切なシーケンスを保証する必要があります。


4

並列受信で何ができるかわかりません。3バイトのメッセージがある場合、1つのスレッドが最初の2バイトを取得し、別のスレッドが最後のバイトを取得できますが、どちらがどちらであるかを知る方法はありません。メッセージの長さが1バイトしかない場合を除き、受信する複数のスレッドで何かを確実に機能させる方法はありません。

メッセージ全体を1回の呼び出しで送信した場合、複数の送信機能する可能性がありますが、よくわかりません。別のものを上書きできる可能性があります。そうすることによるパフォーマンス上の利点は確かにありません。

複数のスレッドが送信する必要がある場合は、同期メッセージキューを実装する必要があります。キューからメッセージを読み取る実際の送信を行う1つのスレッドと、メッセージ全体をエンキューする他のスレッドを用意します。受信でも同じことが機能しますが、受信スレッドはメッセージの形式を知っている必要があるため、メッセージを適切に逆シリアル化できます。


9
SOCK_DGRAMソケットを使用している場合、各recvは単一のデータグラムを取得します。受信間で分割されることはありません
Chris Dodd

2
@noah、並列受信は何もできないことに同意します。それが私がそれを尋ねなかった理由です。私の質問は、並列に送信/受信し、次に複数の送信を並列に行うことです。あなたの答えは並列送信への洞察を与えます。同じことをありがとう。
ジェイ

1
@クリス良い点。私はTCPを想定していました。@Jay並行して受信したいように、「send / recvを並行して呼び出すことができますか?」という質問を明確にするかもしれません。
ノア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.