GNU/Linux >> Linux Esercitazione >  >> Linux

Perché non vedo MSG_EOR per SOCK_SEQPACKET su Linux?

Con i socket di dominio unix SOCK_SEQPACKET l'unico modo per interrompere il messaggio è se il buffer che dai a recvmsg() non è abbastanza grande (e in tal caso otterrai MSG_TRUNC).

POSIX dice che i socket SOCK_SEQPACKET devono impostare MSG_EOR alla fine di un record, ma i socket di dominio unix Linux no.

(Refs:POSIX 2008 2.10.10 dice che SOCK_SEQPACKET deve supportare i record, e 2.10.6 dice che i confini dei record sono visibili al destinatario tramite il flag MSG_EOR.)

Il significato di "record" per un dato protocollo spetta all'implementazione definirlo.

Se Linux implementasse MSG_EOR per i socket di dominio unix, penso che l'unico modo sensato sarebbe dire che ogni pacchetto era un record in sé, e quindi impostare sempre MSG_EOR (o forse impostarlo sempre quando non si imposta MSG_TRUNC), quindi non sarebbe Non essere comunque informativo.


Quando leggi i documenti, SOCK_SEQPACKET differisce da SOCK_STREAM in due modi distinti. Innanzitutto -

Percorso sequenziale, affidabile, bidirezionale basato sulla connessione per datagrammi di lunghezza massima fissa; un consumatore è tenuto a leggere un intero pacchetto con ogni chiamata di sistema in ingresso .

-- socket(2) dal progetto manpage di Linux

ovvero

Per i socket basati sui messaggi, come SOCK_DGRAM e SOCK_SEQPACKET, l'intero messaggio deve essere letto in un'unica operazione. Se un messaggio è troppo lungo per entrare nei buffer forniti e MSG_PEEK non è impostato nell'argomento flags, i byte in eccesso devono essere scartati e MSG_TRUNC deve essere impostato nel membro msg_flags della struttura msghdr.

-- recvmsg() nello standard POSIX.

In questo senso è simile a SOCK_DGRAM .

In secondo luogo ogni "datagramma" (Linux) / "messaggio" (POSIX) porta un flag chiamato MSG_EOR .

Tuttavia Linux SOCK_SEQPACKET per AF_UNIX non implementa MSG_EOR . I documenti attuali non corrispondono alla realtà :-)

Presumibilmente alcuni SOCK_SEQPACKET le implementazioni fanno l'altra. E alcuni implementano entrambi. In modo che copra tutte le possibili diverse combinazioni :-)

[1] I protocolli orientati al pacchetto generalmente utilizzano letture a livello di pacchetto con semantica di troncamento/scarto e senza MSG_EOR. I socket di dominio X.25, Bluetooth, IRDA e Unix utilizzano SOCK_SEQPACKET in questo modo.

[2] I protocolli orientati ai record generalmente utilizzano letture di flussi di byte e MSG_EOR

  • nessuna visibilità a livello di pacchetto, nessun troncamento/scarto. DECNet e ISO TP usano SOCK_SEQPACKET in questo modo.

[3] Gli ibridi pacchetto/record utilizzano generalmente SOCK_SEQPACKET con semantica di troncamento/scarto a livello di pacchetto e pacchetti di terminazione record contrassegnati con MSG_EOR. SPX e XNS SPP usano SOCK_SEQPACKET in questo modo.

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

Hai mostrato un esempio del paragrafo 1.

Il paragrafo 2 si applica anche a SOCK_SEQPACKET come definito per SCTP. Anche se per impostazione predefinita imposta MSG_EOR su ogni sendmsg() . L'opzione per disabilitare questo si chiama SCTP_EXPLICIT_EOR .

Il paragrafo 3, quello più coerente con i documenti, sembra essere il caso più oscuro.

E anche i documenti non sono propriamente coerenti con se stessi.

Il tipo di socket SOCK_SEQPACKET è simile al tipo SOCK_STREAM ed è anch'esso orientato alla connessione. L'unico la differenza tra questi tipi è che i limiti dei record vengono mantenuti utilizzando il tipo SOCK_SEQPACKET . Un record può essere inviato utilizzando una o più operazioni di output e ricevuto utilizzando una o più operazioni di input, ma una singola operazione non trasferisce mai parti di più di un record. I limiti dei record sono visibili al destinatario tramite il flag MSG_EOR nei flag dei messaggi ricevuti restituiti dalla funzione recvmsg(). -- Standard POSIX


Non è a questo che serve MSG_EOR.

Ricorda che l'API dei socket è un'astrazione su un numero di protocolli diversi, inclusi socket del filesystem UNIX, coppie di socket, TCP, UDP e molti molti protocolli di rete diversi, incluso X.25 e alcuni completamente dimenticati.

MSG_EOR serve a segnalare la fine del record dove ha senso per il protocollo sottostante. Cioè. è passare un messaggio al livello successivo che "questo completa un record". Ciò può influire, ad esempio, sul buffering, causando lo svuotamento di un buffer. Ma se il protocollo stesso non ha un concetto di "record" non c'è motivo di aspettarsi che il flag venga propagato.

In secondo luogo, se utilizzi SEQPACKET devi leggere l'intero messaggio in una volta. In caso contrario, il resto verrà scartato. Questo è documentato. In particolare, MSG_EOR è non un flag per dirti che questa è l'ultima parte del pacchetto.

Consiglio:stai ovviamente scrivendo una versione non SEQPACKET da usare su MacOS. Ti suggerisco di scaricare la versione SEQPACKET in quanto raddoppierà solo il carico di manutenzione e codifica. SOCK_STREAM va bene per tutte le piattaforme.


Linux
  1. Linux – Perché usiamo Su – e non solo Su?

  2. Linux – Perché Setuid non funziona??

  3. Perché non esiste un'API DirectX per Linux?

  4. Perché pr_debug del kernel Linux non fornisce alcun output?

  5. Perché questa espressione regolare non funziona su Linux?

Perché mi piace usare bspwm per il mio window manager Linux

Perché scegliere Xfce per il tuo desktop Linux leggero

Perché scegliere Budgie per il tuo desktop Linux

Perché usare il desktop Pantheon per Linux Elementary OS

Il "sistema operativo GNOME" di GNOME non è una distribuzione Linux per tutti [Recensione]

Perché viene visualizzato l'errore:snap "xyz" non trovato?