GNU/Linux >> Znalost Linux >  >> Linux

Proč nevidím MSG_EOR pro SOCK_SEQPACKET na linuxu?

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.


Linux
  1. Linux – proč používáme Su – a nejen Su?

  2. Linux – Proč Setuid nefunguje?

  3. Linux – Proč USB nefunguje v Linuxu, když funguje v Uefi/bios?

  1. Linux – Proč Locale Es_mx funguje, ale Es ne?

  2. Proč pr_debug linuxového jádra nedává žádný výstup?

  3. Linux - Jak zjistím, co čeká na IO disku

  1. Proč mě moje potřeba kontroly přiměla přejít na Linux

  2. Linux vs Windows – Proč je Linux lepší pro programování a vývoj webu

  3. Proč neexistuje rozhraní DirectX API pro Linux?