【问题标题】:Unix socket, SOCK_SEQPACKET vs SOCK_DGRAMUnix 套接字,SOCK_SEQPACKET 与 SOCK_DGRAM
【发布时间】:2012-04-23 15:33:46
【问题描述】:

似乎至少有 3 种不同的本地/unix 套接字类型 (AF_UNIX)、SOCK_STREAMSOCK_DGRAMSOCK_SEQPACKET

虽然我知道SOCK_STREAM 为您提供双向字节流,如 TCP 或双向管道,而另外两个为您提供消息/数据包 API,但 SOCK_DGRAM 的 unix 套接字有什么区别?和SOCK_SEQPACKET

由于这些只是本地的,我想不出有人会以可以重新排序数据包的方式实现SOCK_DGRAM 的充分理由。

另外,SOCK_DGRAM/SOCK_SEQPACKET 是否采用流量控制,或者在阅读速度慢的情况下可以丢弃消息吗?

【问题讨论】:

  • IIRC,SOCK_DGRAM 一次会给你一条消息,而 SOCK_SEQPACKET(对于支持它的协议)将允许你一次读取多个数据报,但总是对数据报进行原子读取,副 SOCK_STREAM您需要自己解析消息边界的地方。
  • 只是注释 SOCK_SEQPACKET 用于 AX.25(业余无线电协议),例如 stackoverflow.com/questions/19040205/…

标签: c unix


【解决方案1】:

这是一篇关于 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 类型。可以使用一个或多个输出发送记录 操作并使用一个或多个输入操作接收,但是 单个操作永远不会传输多个记录的一部分。记录 边界通过 MSG_EOR 标志对接收器可见 接收到由 recvmsg() 函数返回的消息标志。它是 协议特定是否规定了最大记录大小。

【讨论】:

  • 它确实比 PF_UNIX (PF_LOCAL) 套接字更多地谈论 TCP/IP。到目前为止,SOCK_SEQPACKET 和 SOCK_DGRAM 本地套接字之间的唯一真正区别似乎是 SOCK_SEQPACKET 套接字是面向连接的,但是我还是不确定..
  • 嗯,这个答案是错误的。该问题专门询问 PF_UNIX,虽然理想的 SOCK_SEQPACKET 将是比 SOCK_STREAM 高一个抽象级别(在其上提供消息边界),但实现并不是那么理想化。根据this 的说法,PF_UNIX 的实现非常类似于 SOCK_DGRAM,除了......好吧,我真的不知道,这就是我进入这个页面的原因,似乎没有任何答案令人满意。此答案仅适用于更详细的网络协议,这些协议按预期实现 SOCK_SEQPACKET。
  • @lvella:我在回答中引用的链接不仅解释了如何在 TCP 上模拟 SOCK_SEQPACKET(这与 OP 的问题无关),还解释了 SOCK_SEQPACKET 的动机,我认为这是其中之一OP 询问的主要主题。
  • @R.. 问题是,无论 SOCK_SEQPACKET 的动机是什么,这都不是它在 AF_UNIX 上的工作方式,我仍然不知道它为什么存在,因为该实现缺乏确切的区别它来自 SOCK_DGRAM(独立于低级数据报的消息边界标记)。
【解决方案2】:

SOCK_SEQPACKET 为您提供 SOCK_STREAM 的保证(即,保留排序、保证交付、无重复),但与 SOCK_DGRAM 一样具有划定的数据包边界。所以,基本上它是两种协议类型的混合。

在 TCP/IP 系列中,SCTP 实现了 SOCK_STREAM(类 TCP)和 SOCK_SEQPACKET。不幸的是,它在 Windows 上没有库存。

【讨论】:

    【解决方案3】:

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

    当有多个客户端进程与之通信时,这在连接的服务器端(侦听UNIX套接字的进程)很重要: p>

    使用SOCK_DGRAM,您将直接在侦听套接字上获得交错的客户端数据报。使用SOCK_SEQPACKET,您将使用accept 为每个客户端生成一个单独的客户端 套接字,从而分别从每个客户端接收数据报。

    引用man 3 accept:

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

    【讨论】:

      【解决方案4】:

      socket(2) linux 提供的手册页:“DGRAM:数据报(无连接、不可靠消息),SEQPACKET:用于数据报的有序、可靠、[双向]基于连接的数据传输路径”。显着差异。

      unix(7) linux 提供的联机帮助页说:“SOCK_DGRAM,用于 面向数据报 的套接字,它保留消息边界 [但不一定顺序] [...] SOCK_SEQPACKET,用于 >面向连接的套接字,保留消息边界并按发送顺序传递消息。”

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

      Linux 中的 af_file/af_unix 实现中存在流控制,但这根本不需要与标准指定行为相关联。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 2020-08-17
          • 2019-02-12
          • 2017-10-05
          • 1970-01-01
          • 2021-06-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-18
          相关资源
          最近更新 更多