SOCK_SEQPACKET UNIX ドメイン ソケットでは、メッセージを短くする唯一の方法は、recvmsg() に与えるバッファが十分に大きくない場合です (その場合、MSG_TRUNC を取得します)。
POSIX では、SOCK_SEQPACKET ソケットはレコードの末尾に MSG_EOR を設定する必要があると述べていますが、Linux unix ドメイン ソケットは設定していません。
(参照:POSIX 2008 2.10.10 は、SOCK_SEQPACKET がレコードをサポートする必要があると述べており、2.10.6 は、レコード境界が MSG_EOR フラグを介して受信者に見えると述べています。)
特定のプロトコルの「レコード」が何を意味するかは、定義する実装次第です。
Linux が UNIX ドメイン ソケットに MSG_EOR を実装した場合、唯一の賢明な方法は、各パケットはそれ自体がレコードであり、常に MSG_EOR を設定する (または、MSG_TRUNC を設定しない場合は常に設定する) ことであると思います。とにかく有益であってはなりません。
ドキュメントを読むと、SOCK_SEQPACKET
SOCK_STREAM
とは異なります 2 つの異なる方法で。まず -
固定最大長のデータグラム用の、順序付けられた、信頼性の高い、双方向の接続ベースのデータ伝送パス。コンシューマーは、各入力システム コールでパケット全体を読み取る必要があります .
-- socket(2)
Linux manpage プロジェクトから
別名
<ブロック引用>SOCK_DGRAM や SOCK_SEQPACKET などのメッセージベースのソケットの場合、メッセージ全体を 1 回の操作で読み取る必要があります。メッセージが長すぎて提供されたバッファに収まらず、フラグ引数に MSG_PEEK が設定されていない場合、余分なバイトは破棄され、MSG_TRUNC が msghdr 構造体の msg_flags メンバに設定されます。
-- recvmsg()
POSIX 標準で。
この意味では、SOCK_DGRAM
に似ています。 .
次に、各「データグラム」(Linux) /「メッセージ」(POSIX) には、MSG_EOR
というフラグが付けられます。 .
ただし Linux SOCK_SEQPACKET
AF_UNIX
の場合 MSG_EOR
を実装していません .現在のドキュメントは現実と一致しません:-)
伝えられるところによると、いくつかの SOCK_SEQPACKET
実装はもう一方を行います。また、両方を実装するものもあります。これで考えられるさまざまな組み合わせがすべてカバーされました:-)
[1] パケット指向プロトコルは、一般に、切り捨て/破棄セマンティクスを使用し、MSG_EOR を使用しないパケット レベルの読み取りを使用します。 X.25、Bluetooth、IRDA、および Unix ドメイン ソケットは、このように SOCK_SEQPACKET を使用します。
[2] レコード指向プロトコルは、通常、バイト ストリーム読み取りと MSG_EOR を使用します
- パケット レベルの可視性はなく、切り捨てや破棄もありません。 DECNet と ISO TP は SOCK_SEQPACKET をそのように使用します。
[3] パケット/レコード ハイブリッドは、通常、パケット レベルでの切り捨て/破棄セマンティクスを備えた SOCK_SEQPACKET を使用し、MSG_EOR でマークされたレコード終了パケットを使用します。 SPX と XNS SPP は、このように SOCK_SEQPACKET を使用します。
https://mailarchive.ietf.org/arch/msg/tsvwg/9pDzBOG1KQDzQ2wAul5vnAjrRkA
段落 1 の例を示しました。
パラグラフ 2 は SOCK_SEQPACKET
にも適用されます SCTP の定義どおり。デフォルトでは MSG_EOR
に設定されていますが sendmsg()
ごとに .これを無効にするオプションは SCTP_EXPLICIT_EOR
と呼ばれます .
ドキュメントと最も一致しているパラグラフ 3 は、最もあいまいなケースのようです。
そして、ドキュメントでさえ、それ自体と適切に一致していません.
<ブロック引用>
SOCK_SEQPACKET ソケット タイプは SOCK_STREAM タイプに似ており、接続指向でもあります。 唯一 これらのタイプの違いは、レコード境界が SOCK_SEQPACKET タイプを使用して維持されることです
それは MSG_EOR の目的ではありません。
ソケット API は、UNIX ファイルシステム ソケット、ソケットペア、TCP、UDP、および X.25 や完全に忘れ去られたものを含む多くの異なるネットワーク プロトコルを含む、さまざまなプロトコルの抽象化であることを思い出してください。
MSG_EOR は、基礎となるプロトコルにとって意味のある記録の終わりを知らせるためのものです。つまり「これでレコードが完成する」というメッセージを次の層に渡すことです。これは、たとえばバッファリングに影響を与え、バッファのフラッシュを引き起こす可能性があります。しかし、プロトコル自体に「レコード」の概念がない場合、フラグが伝播されることを期待する理由はありません。
次に、SEQPACKET を使用する場合は必須です。 メッセージ全体を一度に読む。そうしないと、残りは破棄されます。それは文書化されています。特に、MSG_EOR はではありません これがパケットの最後の部分であることを示すフラグ。
アドバイス:あなたは明らかに、MacOS で使用する非 SEQPACKET バージョンを作成しています。メンテナンスとコーディングの負担が 2 倍になるだけなので、SEQPACKET バージョンをダンプすることをお勧めします。 SOCK_STREAM はすべてのプラットフォームで問題ありません。