S unixovými doménovými sokety SOCK_SEQPACKET lze zprávu zkrátit pouze v případě, že vyrovnávací paměť, kterou poskytujete recvmsg(), není dostatečně velká (a v takovém případě získáte MSG_TRUNC).
POSIX říká, že SOCK_SEQPACKET sokety musí nastavit MSG_EOR na konec záznamu, ale linuxové unixové sokety nikoli.
(Odkazy:POSIX 2008 2.10.10 říká, že SOCK_SEQPACKET musí podporovat záznamy a 2.10.6 říká, že hranice záznamu jsou viditelné pro přijímač prostřednictvím příznaku MSG_EOR.)
Co znamená „záznam“ pro daný protokol, je na implementaci, kterou definuje.
Pokud by Linux implementoval MSG_EOR pro unixové doménové sokety, myslím, že jediným rozumným způsobem by bylo říci, že každý paket byl záznam sám o sobě, a tak vždy nastavit MSG_EOR (nebo možná vždy nastavit, když nenastavujete MSG_TRUNC), takže by to nebylo stejně nebuďte informativní.
Až budete číst dokumenty, SOCK_SEQPACKET
se liší od SOCK_STREAM
dvěma odlišnými způsoby. Za prvé -
Sekvenovaná, spolehlivá, obousměrná cesta přenosu dat založená na spojení pro datagramy pevné maximální délky; spotřebitel je povinen přečíst celý paket s každým vstupním systémovým voláním .
--
socket(2)
z Linux manpages project
aka
U soketů založených na zprávách, jako je SOCK_DGRAM a SOCK_SEQPACKET, musí být celá zpráva přečtena v jediné operaci. Pokud je zpráva příliš dlouhá na to, aby se vešla do dodaných vyrovnávacích pamětí a v argumentu flags není nastavena MSG_PEEK, přebytečné bajty se zahodí a MSG_TRUNC se nastaví v členu msg_flags struktury msghdr.
--
recvmsg()
ve standardu POSIX.
V tomto smyslu je podobný SOCK_DGRAM
.
Za druhé, každý "datagram" (Linux) / "zpráva" (POSIX) nese příznak nazvaný MSG_EOR
.
Nicméně Linux SOCK_SEQPACKET
pro AF_UNIX
neimplementuje MSG_EOR
. Současné dokumenty neodpovídají realitě :-)
Údajně nějaký SOCK_SEQPACKET
implementace dělají to druhé. A někteří implementují obojí. Takže to pokrývá všechny možné různé kombinace :-)
[1] Paketově orientované protokoly obecně používají čtení na úrovni paketů se sémantikou zkrácení / zahození a bez MSG_EOR. Doménové sokety X.25, Bluetooth, IRDA a Unix tímto způsobem používají SOCK_SEQPACKET.
[2] Protokoly orientované na záznam obecně používají čtení byte stream a MSG_EOR
- žádná viditelnost na úrovni paketů, žádné zkrácení / zahození. DECNet a ISO TP používají SOCK_SEQPACKET tímto způsobem.
[3] Hybridní pakety/záznamy obecně používají SOCK_SEQPACKET se sémantikou zkrácení/zahození na úrovni paketu a pakety ukončující záznam označené MSG_EOR. SPX a XNS SPP používají SOCK_SEQPACKET tímto způsobem.
https://mailarchive.ietf.org/arch/msg/tsvwg/9pDzBOG1KQDzQ2wAul5vnAjrRkA
Ukázali jste příklad odstavce 1.
Odstavec 2 platí také pro SOCK_SEQPACKET
jak je definováno pro SCTP. I když ve výchozím nastavení nastavuje MSG_EOR
každých sendmsg()
. Možnost zakázat toto se nazývá SCTP_EXPLICIT_EOR
.
Odstavec 3, který je nejvíce v souladu s dokumenty, se zdá být nejobskurnějším případem.
A dokonce ani dokumenty nejsou správně konzistentní samy se sebou.
Typ soketu SOCK_SEQPACKET je podobný typu SOCK_STREAM a je také orientován na připojení. To jediné rozdíl mezi těmito typy je ten, že hranice záznamu jsou udržovány pomocí typu SOCK_SEQPACKET . Záznam lze odeslat pomocí jedné nebo více výstupních operací a přijmout pomocí jedné nebo více vstupních operací, ale jediná operace nikdy nepřenese části více než jednoho záznamu. Hranice záznamu jsou viditelné pro příjemce prostřednictvím příznaku MSG_EOR v příznacích přijatých zpráv vrácených funkcí recvmsg(). -- Standard POSIX
K tomu MSG_EOR není.
Pamatujte, že rozhraní API soketů je abstrakcí řady různých protokolů, včetně soketů souborového systému UNIX, párů soketů, TCP, UDP a mnoha různých síťových protokolů, včetně X.25 a některých zcela zapomenutých.
MSG_EOR má signalizovat konec záznamu tam, kde to dává smysl pro základní protokol. Tj. je předat další vrstvě zprávu, že „tímto je záznam dokončen“. To může ovlivnit například ukládání do vyrovnávací paměti, což způsobí vyprázdnění vyrovnávací paměti. Ale pokud samotný protokol nemá koncept „záznamu“, není důvod očekávat, že se příznak bude šířit.
Za druhé, pokud používáte SEQPACKET, musíte přečíst celou zprávu najednou. Pokud tak neučiníte, zbytek bude vyřazen. To je zdokumentováno. Konkrétně MSG_EOR není příznak, který vám řekne, že toto je poslední část paketu.
Rada:Zjevně píšete verzi bez SEQPACKETu pro použití na MacOS. Doporučuji vypsat verzi SEQPACKET, protože to pouze zdvojnásobí zátěž údržby a kódování. SOCK_STREAM je vhodný pro všechny platformy.