什么是SOCK_DGRAM和SOCK_STREAM?

时间:2011-04-28 08:19:14

标签: c++ sockets protocols tcp

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

我认为海啸基于UDP,但仍然具有类似TCP的功能,例如: TCP公平,友好等。

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

4 个答案:

答案 0 :(得分:43)

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

TCP(SOCK_STREAM)是一种基于连接的协议。建立连接,双方进行对话,直到其中一方或网络错误终止连接。

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

  • 如果发送多个数据包,TCP承诺按顺序发送它们。 UDP没有,所以接收者需要检查它们,如果订单 事项。

  • 如果TCP数据包丢失,发件人可以告诉。 UDP不是这样。

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

  • TCP更健壮,可以进行更多检查。 UDP是一种阴影 重量更轻(减少计算机和网络压力)。

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

答案 1 :(得分:18)

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

  • Internet协议版本4(IPv4):AF_INET
  • IPX / SPX:AF_IPX
  • AppleTalk:AF_APPLETALK
  • NetBIOS:AF_NETBIOS
  • Internet协议版本6(IPv6):AF_INET6
  • 红外数据协会(IrDA):AF_IRDA
  • 蓝牙:AF_BTH

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

  • 顺序,可靠,双向,基于连接的字节流:SOCK_STREAM (IP人员将其称为TCP)
  • 无连接,不可靠的数据报:SOCK_DGRAM (IP人员将其称为UDP的信息)

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

| Address   |       Socket Type        |
| 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      |

重点是:

  • 如果您需要可靠的双向双向基于连接的顺序字节流
  • 您使用“ SOCK_STREAM”
  • 要求
  • sockets API将担心弄清楚您是否需要TCP

类似地,如果我正在通过红外线(IrDA,AF_IRDA)创建套接字:

  • 我不知道 IrDA 中的哪种协议可靠,有序且基于连接
  • 我所知道的是,我想要 某事 ,该可靠,有序且基于连接的

所以你说:

socket(AF_IRDA, SOCK_STREAM, 0);

Sockets会帮我解决这个问题。

奖金

最初只有两个协议选项:

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

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

  • 可靠的消息数据报(SOCK_RDM
  • 基于数据报(SOCK_SEQPACKET)的伪流排序数据包

不能保证任何给定的地址族都支持这样的协议选择;但是有的。

tl; dr:这是请求TCP或UDP的与协议无关的方式。但是,由于地球上没有人再使用AppleTalk,IPX / SPX,IrDA,蓝牙,NetBIOS,因此大多是遗留的。

答案 2 :(得分:7)

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


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

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

库总是将其底层的“真实”套接字创建为数据报套(检查channel.cpp,CChannel::open)。

答案 3 :(得分:-2)

TCP 使用 SOCK_STREAM,UDP 使用 SOCK_DGRAM。