UNIX 域流和数据报套接字的区别?

对于 STREAM 类型和 DATAGRAM 类型 INTERNET 套接字之间的区别,这个问题是 没有。我知道 STREAM 套接字使用 TCP,数据报套接字使用 UDP 和所有的 TCP,UDP 的东西,按顺序到达的数据包,ACK,NACK 等。 我明白这些在互联网上的重要性。

问题1)当我创建一个本地插座的 Unix domain socket 时,插座是 STREAM 插座还是 DATAGRAM 插座又有什么关系呢。这种类型的套接字将数据写入套接字文件,在这种情况下协议是否重要,因为我不是通过网络传输数据?在这种情况下,如果我使用基于 UNIX 的 DATAGRAM 套接字,是否有数据丢失的可能?

问2) UNIX DATAGRAM 套接字是否比 UNIX 流套接字提供更好的性能?

Q3)如何决定在我的应用程序中使用基于 STREAM/DATAGRAM UNIX 的套接字?


谢谢

43011 次浏览
  1. One likely difference are message boundaries. Datagrams will be delivered as a whole with the datagrams being the natural message boundaries. With stream sockets you can read N bytes and the socket will block until N bytes are ready. But this means no obvious message boundaries.

  2. All things being equal, if speed is a concern, instrument and measure. (I assume you already know that only a stream socket provides built-in reliable in-order transport, and only datagram sockets can be used to send to multiple receivers).

Just as the manual page says Unix sockets are always reliable. The difference between SOCK_STREAM and SOCK_DGRAM is in the semantics of consuming data out of the socket.

Stream socket allows for reading arbitrary number of bytes, but still preserving byte sequence. In other words, a sender might write 4K of data to the socket, and the receiver can consume that data byte by byte. The other way around is true too - sender can write several small messages to the socket that the receiver can consume in one read. Stream socket does not preserve message boundaries.

Datagram socket, on the other hand, does preserve these boundaries - one write by the sender always corresponds to one read by the receiver (even if receiver's buffer given to read(2) or recv(2) is smaller then that message).

So if your application protocol has small messages with known upper bound on message size you are better off with SOCK_DGRAM since that's easier to manage.

If your protocol calls for arbitrary long message payloads, or is just an unstructured stream (like raw audio or something), then pick SOCK_STREAM and do the required buffering.

Performance should be the same since both types just go through local in-kernel memory, just the buffer management is different.

The main difference is that one is connection based (STREAM) and the other is connection-less (DGRAM) - the difference between stream and packet oriented communication is usually much less important.

With SOCK_STREAM you still get all the connection handling, i.e. listen/accept and you can tell if a connection is closed by the other side.

Note that there is also a SEQPACKET socket type that's still connection oriented, but preserves message boundaries (which might save you from implementing a message-oriented layer on top of a STREAM socket).

I would expect data transfer performance to be similar for all of these types, the main difference is just what semantics you want.

If the clients and servers will always be on the same machine and the goal is to have minimal latency and maximum bandwidth, use shared memory.