Unix socket, SOCK_SEQPACKET vs SOCK_DGRAM
Here is a good article on the intended use case for SOCK_SEQPACKET
, the fact that it's not really available in the IP protocol families, and how you can get the same thing with existing TCP semantics:
http://urchin.earth.li/~twic/Sequenced_Packets_Over_Ordinary_TCP.html
Note that SOCK_SEQPACKET
is much closer in behavior to SOCK_STREAM
than to SOCK_DGRAM
.
Citing from the referenced website:
The SOCK_SEQPACKET socket type is similar to the SOCK_STREAM type, and is also connection-oriented. The only difference between these types is that record boundaries are maintained using the SOCK_SEQPACKET type. A record can be sent using one or more output operations and received using one or more input operations, but a single operation never transfers parts of more than one record. Record boundaries are visible to the receiver via the MSG_EOR flag in the received message flags returned by the recvmsg() function. It is protocol-specific whether a maximum record size is imposed.
SOCK_SEQPACKET gives you the guarantees of SOCK_STREAM (i.e., preservation of ordering, guaranteed delivery, no duplication), but with delineated packet boundaries just like SOCK_DGRAM. So, basically it's a mix of the two protocol types.
In the TCP/IP-family, SCTP implements both SOCK_STREAM (TCP-like) and SOCK_SEQPACKET. Unfortunately it is not stock-available on Windows.
I think the main difference here is that SOCK_SEQPACKET
is conneciton-oriented, while SOCK_DGRAM
is not.
This will mostly matter on the server side of the connection (the process that listens on the UNIX socket) when there are multiple client processes talking to it:
With SOCK_DGRAM
, you would get interleaved client datagrams directly on the listening socket. With SOCK_SEQPACKET
, you would spawn a separate client socket for each client using accept
, thus receiving datagrams from each client separately.
Quoting man 3 accept
:
The accept() system call is used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET).
socket(2) linux-provided manpage: “DGRAM: datagrams (connectionless, unreliable messages), SEQPACKET: sequenced, reliable, [two-way] connection-based data transmission path for datagrams". Significant difference.
unix(7) linux-provided manpage says: “SOCK_DGRAM, for a datagram-oriented socket that preserves message boundaries [but not necessarily order] [...] SOCK_SEQPACKET, for a connection-oriented socket that preserves message boundaries and delivers messages in the order that they were sent.”
The standard permits that you get reordered packets with SOCK_DGRAM. (In other words, if an OS hands them to you in order, that is an implementation-specific feature. Or just pure timing luck.)
There is flow control in the af_file/af_unix implementation in Linux, but that does not need to correlate with standard specified behavior at all.