GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Warum sehe ich MSG_EOR für SOCK_SEQPACKET unter Linux nicht?

Bei SOCK_SEQPACKET-Unix-Domain-Sockets besteht die einzige Möglichkeit zum Kürzen der Nachricht darin, dass der Puffer, den Sie an recvmsg() übergeben, nicht groß genug ist (und in diesem Fall erhalten Sie MSG_TRUNC).

POSIX sagt, dass SOCK_SEQPACKET-Sockets MSG_EOR am Ende eines Datensatzes setzen müssen, Linux-Unix-Domain-Sockets jedoch nicht.

(Referenzen:POSIX 2008 2.10.10 besagt, dass SOCK_SEQPACKET Datensätze unterstützen muss, und 2.10.6 besagt, dass Datensatzgrenzen für den Empfänger über das MSG_EOR-Flag sichtbar sind.)

Was ein „Datensatz“ für ein bestimmtes Protokoll bedeutet, muss von der Implementierung definiert werden.

Wenn Linux MSG_EOR für Unix-Domain-Sockets implementieren würde, wäre meiner Meinung nach der einzig vernünftige Weg zu sagen, dass jedes Paket ein Datensatz für sich ist, und also immer MSG_EOR zu setzen (oder vielleicht immer zu setzen, wenn MSG_TRUNC nicht gesetzt wird), also würde es ' Es ist sowieso nicht informativ.


Wenn Sie die Dokumentation lesen, SOCK_SEQPACKET unterscheidet sich von SOCK_STREAM auf zwei verschiedene Arten. Erstens -

Sequenzierter, zuverlässiger, bidirektionaler verbindungsbasierter Datenübertragungsweg für Datagramme mit fester Maximallänge; ein Konsument muss bei jedem Eingangssystemaufruf ein ganzes Paket lesen .

-- socket(2) aus dem Linux-Manpages-Projekt

auch bekannt als

Bei nachrichtenbasierten Sockets wie SOCK_DGRAM und SOCK_SEQPACKET soll die gesamte Nachricht in einer einzigen Operation gelesen werden. Wenn eine Nachricht zu lang ist, um in die bereitgestellten Puffer zu passen, und MSG_PEEK nicht im Flags-Argument gesetzt ist, werden die überschüssigen Bytes verworfen und MSG_TRUNC wird im msg_flags-Mitglied der msghdr-Struktur gesetzt.

-- recvmsg() im POSIX-Standard.

In diesem Sinne ähnelt es SOCK_DGRAM .

Zweitens trägt jedes „Datagramm“ (Linux) / „Nachricht“ (POSIX) ein Flag namens MSG_EOR .

Allerdings Linux SOCK_SEQPACKET für AF_UNIX implementiert MSG_EOR nicht . Die aktuellen Dokumente stimmen nicht mit der Realität überein :-)

Angeblich einige SOCK_SEQPACKET Implementierungen tun das andere. Und einige implementieren beides. Das deckt also alle möglichen Kombinationen ab :-)

[1] Paketorientierte Protokolle verwenden im Allgemeinen Lesevorgänge auf Paketebene mit Trunkierungs-/Verwerfungssemantik und ohne MSG_EOR. X.25-, Bluetooth-, IRDA- und Unix-Domain-Sockets verwenden SOCK_SEQPACKET auf diese Weise.

[2] Datensatzorientierte Protokolle verwenden im Allgemeinen Bytestream-Lesevorgänge und MSG_EOR

  • keine Sichtbarkeit auf Paketebene, kein Abschneiden/Verwerfen. DECNet und ISO TP verwenden SOCK_SEQPACKET auf diese Weise.

[3] Paket-/Datensatz-Hybride verwenden im Allgemeinen SOCK_SEQPACKET mit Trunkierungs-/Verwerfungs-Semantik auf Paketebene und zeichnen Endpakete auf, die mit MSG_EOR gekennzeichnet sind. SPX und XNS SPP verwenden SOCK_SEQPACKET auf diese Weise.

https://mailarchive.ietf.org/arch/msg/tsvwg/9pDzBOG1KQDzQ2wAul5vnAjrRkA

Sie haben ein Beispiel für Absatz 1 gezeigt.

Absatz 2 gilt auch für SOCK_SEQPACKET wie für SCTP definiert. Obwohl es standardmäßig MSG_EOR setzt auf alle sendmsg() . Die Option zum Deaktivieren heißt SCTP_EXPLICIT_EOR .

Paragraph 3, der am ehesten mit den Dokumenten übereinstimmt, scheint der undurchsichtigste Fall zu sein.

Und selbst die Dokumente stimmen nicht richtig mit sich selbst überein.

Der Socket-Typ SOCK_SEQPACKET ähnelt dem Typ SOCK_STREAM und ist ebenfalls verbindungsorientiert. Der einzige Der Unterschied zwischen diesen Typen besteht darin, dass Datensatzgrenzen mithilfe des Typs SOCK_SEQPACKET beibehalten werden . Ein Datensatz kann mit einer oder mehreren Ausgabeoperationen gesendet und mit einer oder mehreren Eingabeoperationen empfangen werden, aber eine einzelne Operation überträgt niemals Teile von mehr als einem Datensatz. Datensatzgrenzen sind für den Empfänger über das MSG_EOR-Flag in den empfangenen Nachrichten-Flags sichtbar, die von der Funktion recvmsg() zurückgegeben werden. -- POSIX-Standard


Dafür ist MSG_EOR nicht da.

Denken Sie daran, dass die Sockets-API eine Abstraktion über eine Reihe verschiedener Protokolle ist, darunter UNIX-Dateisystem-Sockets, Socketpairs, TCP, UDP und viele, viele verschiedene Netzwerkprotokolle, einschließlich X.25 und einige völlig vergessene.

MSG_EOR soll das Ende des Datensatzes signalisieren, wo dies für das zugrunde liegende Protokoll sinnvoll ist. D.h. Es soll eine Nachricht an die nächste Schicht weitergeben, dass "dies eine Aufzeichnung vervollständigt". Dies kann sich beispielsweise auf das Puffern auswirken und das Leeren eines Puffers verursachen. Aber wenn das Protokoll selbst kein Konzept eines "Records" hat, gibt es keinen Grund zu erwarten, dass das Flag weitergegeben wird.

Zweitens, wenn Sie SEQPACKET verwenden, müssen Sie es müssen Lesen Sie die gesamte Nachricht auf einmal. Wenn Sie dies nicht tun, wird der Rest verworfen. Das ist dokumentiert. Insbesondere ist MSG_EOR nicht ein Flag, das Ihnen mitteilt, dass dies der letzte Teil des Pakets ist.

Hinweis:Sie schreiben offensichtlich eine Nicht-SEQPACKET-Version zur Verwendung auf MacOS. Ich schlage vor, dass Sie die SEQPACKET-Version löschen, da sie den Wartungs- und Codierungsaufwand nur verdoppelt. SOCK_STREAM ist für alle Plattformen geeignet.


Linux
  1. Warum mich mein Bedürfnis nach Kontrolle dazu gebracht hat, zu Linux zu wechseln

  2. Linux – Warum verwenden wir Su – und nicht nur Su?

  3. Linux – Warum funktioniert USB nicht in Linux, wenn es in Uefi/Bios funktioniert?

  4. Linux Vs Windows – Warum Linux besser für Programmierung und Webentwicklung ist

  5. Warum gibt pr_debug des Linux-Kernels keine Ausgabe aus?

Warum ich bspwm so gerne für meinen Linux-Fenstermanager verwende

Warum Xfce für Ihren leichtgewichtigen Linux-Desktop wählen?

Warum Budgie für Ihren Linux-Desktop wählen

Warum den Pantheon-Desktop für Linux Elementary OS verwenden

GNOMEs ganz eigenes „GNOME OS“ ist keine Linux-Distribution für jedermann [Review]

Warum sehen Sie den Fehler:Snap „xyz“ nicht gefunden?