什么是SOCK_DGRAM和SOCK_STREAM?

ech*_*ho9 32 c++ sockets tcp protocols

我刚看到这个奇怪的东西,我看到应用程序是默认情况下他们使用的SOCK_STREAM功能.为什么会这样?这SOCK_STREAM只是创建多个流吗?或者它是SOCK_STREAM可用于创建TCP流的标准功能?

我认为海啸基于UDP,但仍然具有TCP的一些功能,例如TCP公平性,友好性等.

有人可以就这个问题说清楚吗?我完全对此感到困惑.

Mic*_*l J 51

TCP几乎总是使用SOCK_STREAM,UDP使用SOCK_DGRAM.

TCP/SOCK_STREAM是基于连接的协议.建立连接并且双方进行对话,直到连接被一方或网络错误终止.

UDP/SOCK_DGRAM是基于数据报的协议.您发送一个数据报并获得一个回复,然后连接终止.

  • 如果您发送多个数据包,TCP承诺按顺序提供它们.UDP没有,所以接收者需要检查它们,如果顺序重要.

  • 如果TCP数据包丢失,发件人可以告诉.对UDP来说并非如此.

  • UDP数据报的大小有限,从内存我认为是512字节.TCP可以发送比这更大的块.

  • TCP更健壮,可以进行更多检查.UDP的重量更轻(计算机和网络压力更小).

选择适合您希望与其他计算机进行交互的协议.

  • UDP/SOCK_DGRAM 是一种基于数据报的协议,不涉及连接。您发送任意数量的数据报并接收任意数量的数据报。这是一种“不可靠的服务”。 (2认同)
  • TCP/SOCK_STREAM 是“可靠”或“已确认”服务,因为数据包按顺序传递,或者连接终止。保证是,如果数据可能尚未交付,您会收到通知。 (2认同)

Ian*_*oyd 35

Berkley Sockets API背后的想法之一是它可以使用不同的协议系列——而不仅仅是互联网协议 (IP)。但是相反,您拥有一个可以处理各种“地址族”的API ,例如:

  • Internet 协议版本 4 (IPv4): AF_INET
  • IPX/SPX: AF_IPX
  • 苹果谈话: AF_APPLETALK
  • 网络BIOS: AF_NETBIOS
  • 互联网协议版本 6 (IPv6): AF_INET6
  • 红外数据协会 (IrDA): AF_IRDA
  • 蓝牙: AF_BTH

每个协议族通常都有一些关于如何在套接字上处理数据的类似概念:

  • 有序的、可靠的、双向的、基于连接的、字节流:SOCK_STREAM (IP 人员会称之为 TCP)
  • 无连接、不可靠的数据报:SOCK_DGRAM (IP 人员会称之为 UDP)

不同的地址族对这些基本概念有不同的术语:

????????????????????????????????????????
?           ?       Socket Type        ?
? Address   ????????????????????????????
? Family    ? SOCK_DGRAM ? SOCK_STREAM ? 
????????????????????????????????????????
? IPX/SPX   ? SPX        ? IPX         ?
? NetBIOS   ? NetBIOS    ? n/a         ?
? IPv4      ? UDP        ? TCP         ?
? AppleTalk ? DDP        ? ADSP        ?
? IPv6      ? UDP        ? TCP         ?
? IrDA      ? IrLMP      ? IrTTP       ?
? Bluetooth ? ?          ? RFCOMM      ?
????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

重点是:

  • 如果你想要可靠的、双向的、基于连接的、有序的、字节流
  • 您使用“SOCK_STREAM”请求它
  • 并且套接字API 会担心弄清楚您是否需要 TCP

同样,如果我在红外线(IrDA,AF_IRDA)上创建一个套接字:

  • 我不知道IrDA 中的哪种协议是可靠的、有序的和基于连接的
  • 我只知道我想要一些可靠的、顺序的和基于连接的东西

所以你说:

socket(AF_IRDA, SOCK_STREAM, 0);
Run Code Online (Sandbox Code Playgroud)

Sockets 会帮我解决这个问题。

奖金

最初只有两个协议选项:

  • 无连接、不可靠、数据报 ( SOCK_DGRAM)
  • 基于连接的、可靠的、有序的、双向的 ( SOCK_STREAM)

后来添加了其他协议选择:

  • 可靠的消息数据报(SOCK_RDM- “可靠数据报组播” -已过时;未在新程序中使用)
  • 基于数据报的伪流排序数据包 ( SOCK_SEQPACKET)
????????????????????????????????????????????????????????????????????
?           ?                      Socket Type                     ?
? Address   ????????????????????????????????????????????????????????
? Family    ? SOCK_DGRAM ? SOCK_STREAM ? SOCK_RDM ? SOCK_SEQPACKET ? 
????????????????????????????????????????????????????????????????????
? IPX/SPX   ? SPX        ? IPX         ? ?        ? ?              ?
? NetBIOS   ? NetBIOS    ? n/a         ? ?        ? ?              ?
? IPv4      ? UDP        ? TCP         ? ?        ? ?              ?
? AppleTalk ? DDP        ? ADSP        ? ?        ? ?              ?
? IPv6      ? UDP        ? TCP         ? ?        ? ?              ?
? IrDA      ? IrLMP      ? IrTTP       ? ?        ? ?              ?
? Bluetooth ? ?          ? RFCOMM      ? ?        ? ?              ?
????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

不能保证任何给定的地址族都支持此类协议选择;但有些人会。

tl;dr:这是一种独立于协议的请求 TCP 或 UDP 的方式。但是因为地球上没有人再使用 AppleTalk、IPX/SPX、IrDA、蓝牙、NetBIOS,所以它大多是残留的。

  • 我认为没有理由这不应该是最受接受的答案 (4认同)

Cod*_*ers 7

更新:我的答案似乎没有更多相关性,但最初的问题涉及UDT,这是一种建立在UDP之上的面向连接的协议.更多信息:http://en.wikipedia.org/wiki/UDP-based_Data_Transfer_Protocol


UDT似乎提供了模仿经典BSD套接字API的API,因此它可以用作流和面向数据报的应用程序的替代品.检查eg sendmsgrecvmsg- 如果在创建的套接字上使用SOCK_STREAM,则抛出异常,并且所有面向流的API都会为使用它创建的套接字抛出异常SOCK_DGRAM.

SOCK_DGRAM但是,如果它执行一些额外的处理,它不会简单地在这种情况下透明地包装UDP套接字 - 据我快速审查后了解代码(我不熟悉UDT内部或协议规范).阅读技术论文可能会有很大帮助.

该库总是将其底层的"真实"套接字创建为数据报(查看channel.cpp CChannel::open).