Avec les sockets de domaine UNIX SOCK_SEQPACKET, la seule façon d'écourter le message est si le tampon que vous donnez à recvmsg() n'est pas assez grand (et dans ce cas, vous obtiendrez MSG_TRUNC).
POSIX indique que les sockets SOCK_SEQPACKET doivent définir MSG_EOR à la fin d'un enregistrement, mais pas les sockets de domaine Linux Unix.
(Réfs :POSIX 2008 2.10.10 indique que SOCK_SEQPACKET doit prendre en charge les enregistrements, et 2.10.6 indique que les limites d'enregistrement sont visibles pour le récepteur via l'indicateur MSG_EOR.)
Ce qu'un "enregistrement" signifie pour un protocole donné, c'est à l'implémentation de le définir.
Si Linux implémentait MSG_EOR pour les sockets de domaine Unix, je pense que le seul moyen sensé serait de dire que chaque paquet était un enregistrement en soi, et donc de toujours définir MSG_EOR (ou peut-être toujours de le définir sans définir MSG_TRUNC), donc ce serait ' ne soyez pas informatif de toute façon.
Lorsque vous lisez les docs, SOCK_SEQPACKET
diffère de SOCK_STREAM
de deux manières distinctes. Tout d'abord -
Chemin de transmission de données séquencé, fiable, basé sur une connexion bidirectionnelle pour les datagrammes de longueur maximale fixe ; un consommateur doit lire un paquet entier à chaque appel système d'entrée .
--
socket(2)
du projet de pages de manuel Linux
alias
Pour les sockets basés sur les messages, tels que SOCK_DGRAM et SOCK_SEQPACKET, le message entier doit être lu en une seule opération. Si un message est trop long pour tenir dans les tampons fournis et que MSG_PEEK n'est pas défini dans l'argument flags, les octets en excès doivent être ignorés et MSG_TRUNC doit être défini dans le membre msg_flags de la structure msghdr.
--
recvmsg()
dans la norme POSIX.
En ce sens, il est similaire à SOCK_DGRAM
.
Deuxièmement, chaque "datagramme" (Linux) / "message" (POSIX) porte un drapeau appelé MSG_EOR
.
Cependant Linux SOCK_SEQPACKET
pour AF_UNIX
n'implémente pas MSG_EOR
. Les docs actuelles ne correspondent pas à la réalité :-)
Prétendument quelques SOCK_SEQPACKET
les implémentations font l'autre. Et certains mettent en œuvre les deux. Cela couvre donc toutes les différentes combinaisons possibles :-)
[1] Les protocoles orientés paquets utilisent généralement des lectures au niveau des paquets avec une sémantique de troncature/élimination et pas de MSG_EOR. Les sockets de domaine X.25, Bluetooth, IRDA et Unix utilisent SOCK_SEQPACKET de cette façon.
[2] Les protocoles orientés enregistrement utilisent généralement des lectures de flux d'octets et MSG_EOR
- pas de visibilité au niveau des paquets, pas de troncature/suppression. DECNet et ISO TP utilisent SOCK_SEQPACKET de cette façon.
[3] Les hybrides paquet/enregistrement utilisent généralement SOCK_SEQPACKET avec une sémantique de troncature/discard au niveau du paquet, et enregistrent les paquets de terminaison marqués avec MSG_EOR. SPX et XNS SPP utilisent SOCK_SEQPACKET de cette façon.
https://mailarchive.ietf.org/arch/msg/tsvwg/9pDzBOG1KQDzQ2wAul5vnAjrRkA
Vous avez montré un exemple du paragraphe 1.
Le paragraphe 2 s'applique également à SOCK_SEQPACKET
tel que défini pour SCTP. Bien que par défaut, il définit MSG_EOR
sur chaque sendmsg()
. L'option pour désactiver cela s'appelle SCTP_EXPLICIT_EOR
.
Le paragraphe 3, celui qui correspond le mieux à la documentation, semble être le cas le plus obscur.
Et même les documents ne sont pas suffisamment cohérents avec eux-mêmes.
Le type de socket SOCK_SEQPACKET est similaire au type SOCK_STREAM et est également orienté connexion. Le seul la différence entre ces types est que les limites d'enregistrement sont maintenues à l'aide du type SOCK_SEQPACKET . Un enregistrement peut être envoyé en utilisant une ou plusieurs opérations de sortie et reçu en utilisant une ou plusieurs opérations d'entrée, mais une seule opération ne transfère jamais des parties de plus d'un enregistrement. Les limites d'enregistrement sont visibles pour le destinataire via l'indicateur MSG_EOR dans les indicateurs de message reçu renvoyés par la fonction recvmsg(). -- Norme POSIX
Ce n'est pas à cela que sert MSG_EOR.
N'oubliez pas que l'API sockets est une abstraction sur un certain nombre de protocoles différents, y compris les sockets du système de fichiers UNIX, les paires de sockets, TCP, UDP et de nombreux protocoles réseau différents, y compris X.25 et certains totalement oubliés.
MSG_EOR est de signaler la fin de l'enregistrement là où cela a du sens pour le protocole sous-jacent. C'est à dire. c'est pour transmettre un message à la couche suivante que "ceci complète un enregistrement". Cela peut affecter, par exemple, la mise en mémoire tampon, provoquant le vidage d'une mémoire tampon. Mais si le protocole lui-même n'a pas de concept d'"enregistrement", il n'y a aucune raison de s'attendre à ce que le drapeau soit propagé.
Deuxièmement, si vous utilisez SEQPACKET, vous devez lire tout le message d'un coup. Si vous ne le faites pas, le reste sera jeté. C'est documenté. En particulier, MSG_EOR n'est pas un indicateur pour vous indiquer qu'il s'agit de la dernière partie du paquet.
Conseil :Vous écrivez évidemment une version non-SEQPACKET pour une utilisation sur MacOS. Je vous suggère de vider la version SEQPACKET car elle ne fera que doubler la charge de maintenance et de codage. SOCK_STREAM convient à toutes les plates-formes.