Unix套接字,SOCK_SEQPACKET vs SOCK_DGRAM

65

看起来至少有三种不同的本地/Unix套接字类型(AF_UNIX),SOCK_STREAMSOCK_DGRAMSOCK_SEQPACKET

我知道SOCK_STREAM提供双向字节流,例如TCP或双向管道,而其他两个提供消息/数据包API。那么SOCK_DGRAMSOCK_SEQPACKET之间有什么区别呢?

由于这些都是局域网通信,我无法想象为什么会有人以可能重新排序数据包的方式实现SOCK_DGRAM

此外,SOCK_DGRAM/SOCK_SEQPACKET是否采用流量控制,或者在读取速度较慢时消息是否会被丢弃?


如果我没记错的话,SOCK_DGRAM每次只会给你一个消息,而SOCK_SEQPACKET(适用于支持它的协议)将允许您一次读取多个数据报,但始终提供数据报的原子读取,与SOCK_STREAM不同,您需要自己解析消息边界。 - tbert
2
只是一条注释,SOCK_SEQPACKET 在 AX.25(业余无线电协议)中使用,例如请参见 https://dev59.com/dHfZa4cB1Zd3GeqPQFJ6。 - Steven R. Loomis
5个回答

31
这是一篇关于SOCK_SEQPACKET的使用案例的好文章,实际上它在IP协议族中并不真正可用,但您可以通过现有的TCP语义来获得相同的东西。请参考以下网址:http://urchin.earth.li/~twic/Sequenced_Packets_Over_Ordinary_TCP.html 需要注意的是,SOCK_SEQPACKET的行为与SOCK_STREAM比较接近,而不是与SOCK_DGRAM
引用自参考网站:
“SOCK_SEQPACKET”套接字类型类似于“SOCK_STREAM”类型,也是面向连接的。这些类型之间唯一的区别是使用“SOCK_SEQPACKET”类型维护记录边界。可以使用一个或多个输出操作发送记录,并使用一个或多个输入操作接收记录,但是单个操作从不传输超过一个记录的部分。通过recvmsg()函数返回的接收消息标志中的MSG_EOR标志,记录边界对接收者可见。是否强制执行最大记录大小取决于协议。

1
它更多地涉及TCP/IP而不是PF_UNIX(PF_LOCAL)套接字。到目前为止,似乎SOCK_SEQPACKET和SOCK_DGRAM本地套接字之间唯一的真正区别是SOCK_SEQPACKET套接字是面向连接的,但我仍然不确定。 - user1255770
这个答案是错误的。问题明确要求关于PF_UNIX,虽然理想的SOCK_SEQPACKET比SOCK_STREAM更高一级(在其上提供消息边界),但实现并不那么理想化。根据此文,PF_UNIX实现非常类似于SOCK_DGRAM,除了...好吧,我真的不知道,这就是为什么我来到这个页面,而且没有一个答案看起来令人满意。这个答案仅适用于更复杂的网络协议,实现了SOCK_SEQPACKET应该有的功能。 - lvella
1
@lvella:我在回答中引用的链接不仅解释了如何在TCP上模拟SOCK_SEQPACKET(这与OP的问题无关),还解释了SOCK_SEQPACKET的动机,我认为这是OP主要询问的一个主题。 - R.. GitHub STOP HELPING ICE
1
@R.. 问题是,无论 SOCK_SEQPACKET 的动机是什么,在 AF_UNIX 上它并不是这样工作的,而且我仍然不知道为什么它存在,因为其实现缺少了应该将其与 SOCK_DGRAM 区分开来的精确特征(独立于底层数据报的消息边界标记)。 - lvella

12

SOCK_SEQPACKET提供了SOCK_STREAM的保证(即保留顺序,确保传递,无重复),但是像SOCK_DGRAM一样具有分界的数据包。因此,它基本上是两种协议类型的混合。

在TCP/IP系列中,SCTP实现了SOCK_STREAM(类似于TCP)和SOCK_SEQPACKET。不幸的是,它在Windows上不是默认可用的。


10

我认为这里的主要区别在于SOCK_SEQPACKET面向连接的,而SOCK_DGRAM则不是。

这在连接的服务器端(监听UNIX套接字的进程)中尤为重要,当有多个客户端进程与其通信时:

使用SOCK_DGRAM,你会直接在监听套接字上获取交错的客户端数据报。而使用SOCK_SEQPACKET,你会为每个客户端使用accept生成一个单独的客户端套接字,从而分别接收来自每个客户端的数据报。

引用man 3 accept的话:

accept()系统调用用于基于连接的套接字类型(SOCK_STREAM、SOCK_SEQPACKET)。


6

socket(2)是Linux提供的手册:“DGRAM:数据报(无连接,不可靠的消息),SEQPACKET:序列化、可靠的[双向]基于连接的数据传输路径,用于数据报。”这有重大区别。

unix(7)是Linux提供的手册,它说:“SOCK_DGRAM,用于保留消息边界[但不一定保留顺序]的数据报导向套接字[...] SOCK_SEQPACKET,用于保留消息边界并按发送顺序传递消息的连接导向套接字。”

标准允许使用SOCK_DGRAM获得重新排序的数据包。换句话说,如果操作系统按顺序将它们交给您,那就是实现特定的功能。或者只是纯粹的时间运气。

在Linux中,af_file/af_unix实现中有流量控制,但这与标准指定的行为无需相关联。


0
像TCP和UDP套接字一样,有SCTP(流控制传输协议)套接字,它有两种形式,即(一对一)和(一对多)之间的端点。一对一使用SOCK_STREAM,一对多使用SOCK_SEQPACKET。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接