3

2 つのプロセス (または 2 つのスレッド) 間で 1 つのソケットを共有していて、両方でブロックする大きなメッセージ (下線のプロトコル バッファよりも大きい) を送信しようとした場合、両方のメッセージが順番に送信されることが保証されますか? または、メッセージがカーネル内でインターリーブされる可能性はありますか?

私は主に TCP over IP の動作に関心がありますが、ソケットのプロトコルによって異なるかどうかを知ることは興味深いでしょう。

4

3 に答える 3

5

write()同じソケットで A にメッセージを送信し、次に B にメッセージを送信した場合、A は B の前に到着することが保証されますか? SOCK_STREAM (TCP など) および SOCK_SEQPACKET (ほとんど使用されない) ソケットの場合、答えは無条件に yes です。インターネット上の SOCK_DGRAM (つまり UDP パケット) の場合、答えはノーです。パケットはネットワークによって並べ替えられる可能性があります。単一のホストでは、UNIX ドメイン データグラム ソケットは (私が知っているすべてのシステムで) 順序を保持しますが、それが標準によって保証されているとは思いませんし、エッジ ケースがあると確信しています。

それとも待ってください: 2 つのプロセスによって書き込まれたメッセージが混在しないかどうかを尋ねているのでしょうか? はい: 単一のシステム コール (write/writev/sendto/sendmsg) は、常にその内容をアトミックにファイル記述子に配置します。ただし、明らかに、あなたまたはあなたのライブラリが複数の呼び出しに書き込む場合、その保証は失われます。

于 2012-06-28T05:27:14.637 に答える
2

UDP の場合、2 つのスレッドが同時にソケット ハンドルに書き込むと、両方のメッセージが別々のデータグラムとして送信されます。パケットが MTU よりも大きい場合、IP フラグメンテーションが発生する可能性がありますが、結果のデータグラムは保持され、受信者によって正しく再構築されます。つまり、UDP に関連する通常の問題 (データグラムの並べ替え、パケット損失など) を除いて、UDP に対して安全です。

ストリームベースの TCP については、わかりません。あなたの質問は、本質的に「2 つのスレッドが同じファイル ハンドルに書き込もうとした場合、ファイルはまだ判読可能ですか?」と同等の質問をしています。実は答えはわかりません。

最も簡単な方法は、スレッド セーフ ロック (mutex) を使用してソケットへの送信/書き込み呼び出しを保護し、一度にスレッド上でのみソケットに書き込みできるようにすることです。

TCP の場合、すべてのソケット io を処理するための専用スレッドを用意することをお勧めします。次に、ワーカー スレッドからのメッセージを非同期的にソケット スレッドのキューに入れ、送信できるようにする方法を考案します。ソケット スレッドは recv() 呼び出しを処理し、ソケット接続がリモート側によって終了されたときに他のスレッドに通知することもできます。

于 2012-06-28T06:49:17.133 に答える