SOCK_DGRAM 和 SOCK_STREAM 是啥?
Posted
技术标签:
【中文标题】SOCK_DGRAM 和 SOCK_STREAM 是啥?【英文标题】:What is SOCK_DGRAM and SOCK_STREAM?SOCK_DGRAM 和 SOCK_STREAM 是什么? 【发布时间】:2011-08-14 12:19:10 【问题描述】:我刚刚遇到了一个奇怪的事情,我看到应用程序默认情况下它们使用SOCK_STREAM
函数。为什么会这样?这是SOCK_STREAM
只是创建多个流吗?或者它是可用于创建 TCP 流的标准 SOCK_STREAM
函数?
我认为 tsunami 是基于 UDP 的,但仍然具有一些类似于 TCP 的功能,例如TCP 公平、友好等。
有人可以解释一下这个问题吗?我对此感到非常困惑。
【问题讨论】:
它们不是函数,它们是根据其文档提供给socket()
系统调用的清单常量。
【参考方案1】:
TCP 几乎总是使用SOCK_STREAM
而UDP 使用SOCK_DGRAM
。
TCP (SOCK_STREAM
) 是一种基于连接的协议。连接已建立,并且双方进行对话,直到连接被其中一方或网络错误终止。
UDP (SOCK_DGRAM
) 是一种基于数据报的协议。您发送一个数据报并得到一个回复,然后连接终止。
如果您发送多个数据包,TCP 承诺按顺序传送它们。 UDP没有,所以接收者需要检查它们,如果命令 很重要。
如果 TCP 数据包丢失,发送者可以知道。 UDP 则不然。
UDP 数据报的大小是有限的,从内存我认为是 512 字节。 TCP 可以发送比这更大的块。
TCP 更健壮一些,并且进行更多检查。 UDP是一个阴影 重量更轻(计算机和网络压力更小)。
选择适合您与其他计算机交互方式的协议。
【讨论】:
我使用 EMBOS 的 IP 堆栈。我创建了一个 SOCK_DGRAM 类型的套接字。但是当我收到一个 UDP 数据包时,只有第一次调用 select 函数......在这种情况下是否与套接字类型有关? @GinuJacob - 我对 EMBOS 一无所知。创建一个新问题并选择标签(例如“EMBOS”),以吸引具有合适技能的人来帮助您。 UDP/SOCK_DGRAM 是一种基于数据报的协议,不涉及任何连接。您发送任意数量的数据报并接收任意数量的数据报。这是一项“不可靠的服务”。 TCP/SOCK_STREAM 是一种“可靠”或“已确认”的服务,因为数据包按顺序传送,或者连接终止。保证是如果数据可能尚未交付,您会收到通知。 @JeffLearman 实际上并非如此,UDP 仅被限制(作为协议)为 2^16 字节。无论 MTU 如何,您都可以使用 IP 分片发送非常大的 UDP 数据包,内核将为您重新组装它们【参考方案2】:Berkley Sockets API 背后的一个想法是它可以使用不同的 protocol families - 而不仅仅是互联网协议 (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)
不同的地址族对这些基本概念有不同的称谓:
╔═══════════╦══════════════════════════╗
║ ║ 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 ║
╚═══════════╩════════════╧═════════════╝
重点是:
如果您想要可靠的、双向的、基于连接的、顺序的、字节流 您使用 "SOCK_STREAM" 要求它 和 sockets API 会担心你需要 TCP同样,如果我在红外线上创建一个套接字(IrDA,AF_IRDA
):
所以你说:
socket(AF_IRDA, SOCK_STREAM, 0);
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 │ ? │ SCTP ║
║ AppleTalk ║ DDP │ ADSP │ ? │ ? ║
║ IPv6 ║ UDP │ TCP │ ? │ SCTP ║
║ IrDA ║ IrLMP │ IrTTP │ ? │ ? ║
║ Bluetooth ║ ? │ RFCOMM │ ? │ ? ║
╚═══════════╩════════════╧═════════════╧══════════╧════════════════╝
不保证任何给定的地址族都支持此类协议选择;但有些人会这样做。
奖金奖金聊天
希望现在您明白为什么在调用中传递IPPROTO_TCP
协议以创建套接字是多余的:
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // passing IPPROTO_TCP is redundant
socket(AF_INET, SOCK_STREAM, 0); // better
你已经说过你想要SOCK_STREAM
。你不需要在它上面强制TCP
。以同样的方式调用是多余的:
socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //passing IPPROTO_UDP is redundant
socket(AF_INET, SOCK_DGRAM, 0); // better
tl;dr: 这是一种请求 TCP 或 UDP 的独立于协议的方式。但由于地球上没有人再使用 AppleTalk、IPX/SPX、IrDA、蓝牙、NetBIOS,它大多是退化的。
【讨论】:
我认为这不应该是最被接受的答案 @ArkestMust 您的评论缺乏相关性。 TCP 遍及全球。蓝牙跨越约 100 英尺。无论如何,蓝牙是一个媒体层,而 TCP 是一个会话层协议。根本没有可比性。【参考方案3】:更新:我的回答似乎不再相关,但最初的问题是指 UDT,它是一种建立在 UDP 之上的面向连接的协议。更多信息在这里:http://en.wikipedia.org/wiki/UDP-based_Data_Transfer_Protocol
UDT 似乎提供了模仿经典 BSD 套接字 API 的 API,因此它可以用作面向流和数据报的应用程序的直接替代品。检查例如sendmsg
和 recvmsg
- 如果在使用 SOCK_STREAM
创建的套接字上使用它们都会抛出异常,并且所有面向流的 API 也会对使用 SOCK_DGRAM
创建的套接字抛出异常。
如果是SOCK_DGRAM
,它会执行一些额外的处理,但是在这种情况下它不会简单地透明地包装 UDP 套接字 - 据我在快速查看后理解代码(我不熟悉 UDT 内部或协议规范)。阅读technical papers 会有很大帮助。
该库始终将其底层的“真实”套接字创建为数据报之一(检查 channel.cpp,CChannel::open
)。
【讨论】:
【参考方案4】:TCP 使用 SOCK_STREAM,UDP 使用 SOCK_DGRAM。
【讨论】:
所以你刚刚从第一个答案中复制了第一行。更具体地了解 OP 提出的问题。 @Xenikh 不,他没有。他正确地省略了“几乎总是”这个荒谬的限定词。以上是关于SOCK_DGRAM 和 SOCK_STREAM 是啥?的主要内容,如果未能解决你的问题,请参考以下文章
SOCK_DGRAM 和 SOCK_STREAM 在上下文 AF_UNIX 套接字中的用途是啥?