SOCK_DGRAM和SOCK_STREAM是两种不同的套接字类型。SOCK_DGRAM提供无连接的数据报服务,而SOCK_STREAM提供面向连接的可靠数据流服务。

99

我刚看到一个奇怪的东西,是关于应用程序的,它默认使用SOCK_STREAM函数。为什么要这样做?这个SOCK_STREAM是创建多个流吗?还是标准的SOCK_STREAM函数可用于创建TCP流?

我原以为tsunami是基于UDP的,但仍具有与TCP类似的一些特性,如TCP公平性,友好性等。

请问有人能解答一下这个问题吗?我对此完全感到困惑。


2
它们不是函数,而是清单常量,根据其文档提供给socket()系统调用。 - user207421
5个回答

120

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

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

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

  • 如果您发送多个数据包,TCP承诺按顺序传递它们。 如果顺序很重要,则UDP不会,因此接收方需要检查它们。

  • 如果TCP数据包丢失,发送方可以告诉。 UDP则不能。

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

  • TCP更加稳健,进行更多的检查。 UDP较轻量级(计算机和网络压力较小)。

选择与您与另一台计算机交互的方式相适应的协议。


3
UDP/SOCK_DGRAM是一种基于数据报的协议,不需要建立连接。您可以发送任意数量的数据报并接收任意数量的数据报。它是一种“不可靠的服务”。 - Jeff Learman
2
TCP/SOCK_STREAM是一种“可靠”或“确认”的服务,因为数据包按顺序传递或连接终止。保证您会收到通知,如果数据可能未被传递。 - Jeff Learman
你说的“几乎”是什么意思?TCP 什么时候 使用 SOCK_STREAM?你暗示它们是同义词。你需要澄清。发送方无法判断 TCP 数据包是否丢失,除非通过连接重置。而在 UDP 中根本没有连接,也没有必要的回复,更不用说在正好一次发送和一次响应后终止连接了。答案大部分都是胡说八道。 - user207421
1
@JeffLearman 其实不是这样的,UDP协议只限制在2^16字节内。你可以使用IP分段来发送非常大的UDP数据包,而不受MTU的限制,内核会为您重新组装它们。 - Allison
1
UDP数据包的大小不限于512字节。它们由UDP限制为64K字节。它们还受网络层最大服务数据单元大小的限制。对于启用分片的IPv4,这几乎是64KB。对于禁用分片或IPv6的IPv4,应使用MTU路径发现,特别是在使用大于1500字节的IP数据包时。 - Jeff Learman
显示剩余3条评论

77

Berkley 套接字 API 的一个思想是它可以使用不同的协议族,而不仅仅是互联网协议(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
  • 蓝牙(Bluetooth):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)套接字:

  • 我不知道在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
< p >< em >< strong >总结: 它是一种独立于协议的请求TCP或UDP的方式。但由于地球上没有人再使用AppleTalk、IPX/SPX、IrDA、蓝牙、NetBIOS,因此它基本上是遗留物。


4
我认为这应该是最被接受的答案,没有任何不应该的理由。 - Adam Sperry
@ArkestMust 你的评论缺乏相关性。TCP覆盖全球,而蓝牙仅能覆盖100英尺左右。无论如何,蓝牙是媒体层协议,而TCP是会话层协议。两者根本无法比较。 - user207421
@RemyLebeau 今晚你在这里做什么工作? - Ian Boyd
@RemyLebeau,我的回答已经发布了几年了。我在你发表评论45分钟后看到了它。而且那时是晚上。所以我很好奇你是如何偶然发现我两年前在一个十年历史的问题上的回答的。你在进行一些原始套接字工作吗?这是真正的好奇心 - 因为我们都在这里活跃。 - Ian Boyd
@IanBoyd,你的回答可能已经有2年了,但是Gabriel的回答只有1天。这触发了这个问题出现在我的动态中,所以我对他的回答进行了一些评论。然后我看到了你的回答,并进行了更多的评论。 - Remy Lebeau
显示剩余2条评论

8

更新:我的回答似乎不再相关,但原问题是关于UDT的,它是建立在UDP之上的面向连接的协议。更多信息请参见: http://en.wikipedia.org/wiki/UDP-based_Data_Transfer_Protocol


UDT似乎提供了与经典的BSD sockets API 相似的API,因此它可以用作流和数据报应用程序的替代品。例如,请检查sendmsgrecvmsg - 如果在使用使用SOCK_STREAM创建的套接字上使用这两个函数,它们都会抛出异常;所有面向流的API也会对使用SOCK_DGRAM创建的套接字抛出异常。

SOCK_DGRAM情况下,它会执行一些额外的处理,但在这种情况下并不会简单地透明地将UDP套接字包装起来 - 就我快速评估代码所了解的而言(我不熟悉UDT内部或协议规范),阅读技术论文可能会有所帮助。

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


2

前言:有用的宏

以下是从我为自己编写的常用套接字演示文件中获取UDPTCP数据包的一些有用宏。

来自这些文件:

  1. socket__geeksforgeeks_udp_server_GS_edit_GREAT.c
  2. socket__geeksforgeeks_udp_client_GS_edit_GREAT.c

在这里你可以找到这些宏:

// See: https://linux.die.net/man/7/ip
// AF = "Address Family"
// INET = "Internet"
// AF_INET = IPv4 internet protocols
// AF_INET6 = IPv6 internet protocols; see: https://linux.die.net/man/2/socket
// DGRAM = "Datagram" (UDP)
//
// IPv4
#define SOCKET_TYPE_TCP_IPV4              AF_INET, SOCK_STREAM, 0
#define SOCKET_TYPE_UDP_IPV4              AF_INET, SOCK_DGRAM, 0
#define SOCKET_TYPE_RAW_IPV4(protocol)    AF_INET, SOCK_RAW, (protocol)
// IPv6
#define SOCKET_TYPE_TCP_IPV6              AF_INET6, SOCK_STREAM, 0
#define SOCKET_TYPE_UDP_IPV6              AF_INET6, SOCK_DGRAM, 0
#define SOCKET_TYPE_RAW_IPV6(protocol)    AF_INET6, SOCK_RAW, (protocol)

使用示例:

int socket_tcp = socket(SOCKET_TYPE_TCP_IPV4);
int socket_udp = socket(SOCKET_TYPE_UDP_IPV4);
// See also: https://www.binarytides.com/raw-sockets-c-code-linux/
int socket_raw = socket(SOCKET_TYPE_RAW_IPV4(IPPROTO_RAW));

现在回到问题:
什么是 `SOCK_DGRAM` 和 `SOCK_STREAM`?
简要概述:
UDP --(使用的协议是)--> `AF_INET,SOCK_DGRAM` 或 `AF_INET6,SOCK_DGRAM` TCP --(使用的协议是)--> `AF_INET,SOCK_STREAM` 或 `AF_INET6,SOCK_STREAM`
示例:来自 https://linux.die.net/man/7/ip(或通过运行 `man 7 ip` 在终端中显示的页面):
``` tcp_socket = socket(AF_INET, SOCK_STREAM, 0); udp_socket = socket(AF_INET, SOCK_DGRAM, 0); raw_socket = socket(AF_INET, SOCK_RAW, protocol); ```
详细概述:

请参考 int socket(AddressFamily, Type, Protocol) 套接字创建函数的文档 这里这里 (也可以通过运行 man 2 socket 查看)。它允许您指定这三个参数:

  1. 地址族
  2. 套接字类型
  3. 协议

然而,对于许多(如果不是大多数)用例,这些参数的最有用选项通常是:

  1. 地址族: AF_INET (用于IPv4地址) 或 AF_INET6 (用于IPv6地址)。

  2. 套接字类型: SOCK_DGRAMSOCK_STREAM

  3. 协议: 只需使用0,以允许其使用默认协议,如上面的文档链接中所指定的(强调添加):

    协议: 指定要与套接字一起使用的特定协议。 指定0的协议参数会导致套接字子例程默认为请求返回套接字类型的典型协议。

  4. SOCK_DGRAM: 如果您使用AF_INET创建套接字,则为

    int s = socket(AF_INET, SOCK_DGRAM, 0)
    

    或者使用AF_INET6作为

    int s = socket(AF_INET6, SOCK_DGRAM, 0)
    

    ...当选择(AF_INETAF_INET6)地址族和SOCK_DGRAM套接字类型时,默认情况下套接字使用UDP协议。

    1. UNIX地址族域(AF_UNIX)中: 当通过AF_UNIX地址族在同一操作系统上运行的进程之间进行通信时,这类似于进程间消息队列。
    2. Internet地址族域(AF_INETAF_INET6)中: 当通过AF_INET地址族在本地进程和远程主机上运行的进程之间进行通信时,这是“在用户数据报协议/Internet协议(UDP/IP)协议上实现的”。
  5. SOCK_STREAM: 如果您使用AF_INET创建套接字,则为

    int s = socket(AF_INET, SOCK_STREAM, 0)
    

    或者使用AF_INET6作为

    int s = socket(AF_INET6, SOCK_STREAM, 0)
    

    ...当选择(AF_INETAF_INET6)地址族和SOCK_STREAM套接字类型时,默认情况下套接字使用TCP协议。

    1. UNIX地址族域(AF_UNIX)中: 当通过AF_UNIX地址族在同一操作系统上运行的进程之间进行通信时,这种类型的套接字“类似于管道”IPC(进程间通信)机制。
    2. Internet地址族域(AF_INETAF_INET6)中: 当通过AF_INET地址族在本地进程和远程主机上运行的进程之间进行通信时,这是“在传输控制协议/Internet协议(TCP/IP)协议上实现的”。

细节

在下面的解释中,无论我(或他们,在引用部分中)使用AF_INET(用于IPv4地址),请记住如果您喜欢,也可以使用AF_INET6(用于IPv6地址)。

在基于套接字的通信中,包括在同一台计算机上的两个运行进程之间或在两台不同计算机之间来回发送UDP/IP和TCP/IP以太网数据包,必须同时指定地址族(这些常量以AF_开头)和套接字类型(这些常量以SOCK_开头)。

我发现关于套接字的最好文档来自IBM.com,例如这里:

  1. 函数int socket(AddressFamily, Type, Protocol): https://www.ibm.com/docs/en/aix/7.1?topic=s-socket-subroutine
  2. 地址族:https://www.ibm.com/docs/en/aix/7.1?topic=domains-address-families 和这里
  3. 套接字类型:https://www.ibm.com/docs/en/aix/7.1?topic=protocols-socket-types

想要了解更多关于“套接字”的信息,请点击上述链接之一后在左侧导航面板中查看。

在linux.die.net网站上也可以找到其他优秀的文档,例如这里的ip(7)页面

地址族(AF_)域

从上面的“地址族”链接中,我们首先了解各种套接字地址族(AF)域,这是理解套接字类型的先决条件。以下是该信息(强调部分已添加,并在方括号中添加了我的注释):

一个套接字子程序,它以地址族(AF)作为参数,可以使用 AF_UNIX(UNIX)AF_INET(Internet)AF_NS(Xerox Network Systems)或 AF_NDD(操作系统的网络设备驱动程序)协议。这些地址族是以下通信域的一部分: UNIX:当指定 AF_UNIX 的地址族时,在运行在同一操作系统上的进程之间提供套接字通信。UNIX 域中的套接字名称是由 ASCII 字符串组成的,其最大长度取决于所使用的机器。 Internet:当指定 AF_INET 的地址族时,在本地进程和远程主机上运行的进程之间提供套接字通信。Internet 域要求在您的系统上安装传输控制协议/Internet 协议 (TCP/IP)。Internet 域中的套接字名称是由一个 32 位 IP 地址 [例如:192.168.0.1] 和一个 16 位端口地址 [从 065535 中的任何数字;这里是常见 TCP 和 UDP 端口号列表] 组成的 Internet 地址。 NDD:当指定 AF_NDD 的地址族时,在本地进程和远程主机上运行的进程之间提供套接字通信。NDD 域使应用程序能够直接在物理网络顶部运行。这与 Internet 域不同,Internet 域中的应用程序运行在诸如TCP用户数据报协议 (UDP)等传输协议之上。NDD 域中的套接字名称由操作系统 NDD 名称和第二部分(协议相关)组成。 通信域 [例如:AF_UNIXAF_INET] 由可加载的域数据结构描述。域内的通信协议 [例如:SOCK_DGRAM (UDP) 或 SOCK_STREAM (TCP)] 由为每个配置的协议实现定义的结构描述。当请求创建套接字时,系统使用通信域的名称线性搜索已配置的域列表。如果找到该域,则会查询该域支持的协议表,以查找适合正在创建的套接字类型或特定协议请求的协议。(原始域可能存在通配符条目。)如果多个协议条目满足请求,则选择第一个。

套接字类型 (SOCK_)

从上面的“套接字类型”链接中,我们了解到各种“底层通信协议”(强调添加,我的注释用方括号 [] 表示):

Sockets are classified according to communication properties. Processes usually communicate between sockets of the same type. However, if the underlying communication protocols support the communication, sockets of different types can communicate.

Each socket has an associated type, which describes the semantics of communications using that socket. The socket type determines the socket communication properties such as reliability, ordering, and prevention of duplication of messages. The basic set of socket types is defined in the sys/socket.h file:

/*Standard socket types */
#define  SOCK_STREAM             1 /*virtual circuit*/
#define  SOCK_DGRAM              2 /*datagram*/
#define  SOCK_RAW                3 /*raw socket*/
#define  SOCK_RDM                4 /*reliably-delivered message*/
#define  SOCK_CONN_DGRAM         5 /*connection datagram*/

Other socket types can be defined.

The operating system supports the following basic set of sockets:


SOCK_DGRAM: Provides datagrams, which are connectionless messages of a fixed maximum length. This type of socket is generally used for short messages, such as a name server or time server, because the order and reliability of message delivery is not guaranteed.

In the UNIX domain [AF_UNIX], the SOCK_DGRAM socket type is similar to a message queue. In the Internet domain [AF_INET], the SOCK_DGRAM socket type is implemented on the User Datagram Protocol/Internet Protocol (UDP/IP) protocol.

A datagram socket supports the bidirectional flow of data, which is not sequenced, reliable, or unduplicated. A process receiving messages on a datagram socket may find messages duplicated or in an order different than the order sent. Record boundaries in data, however, are preserved. Datagram sockets closely model the facilities found in many contemporary packet-switched networks.

SOCK_STREAM: Provides sequenced, two-way byte streams with a transmission mechanism for stream data. This socket type transmits data on a reliable basis, in order, and with out-of-band capabilities.

In the UNIX domain [AF_UNIX], the SOCK_STREAM socket type works like a pipe. In the Internet domain [AF_INET], the SOCK_STREAM socket type is implemented on the Transmission Control Protocol/Internet Protocol (TCP/IP) protocol.

A stream socket provides for the bidirectional, reliable, sequenced, and unduplicated flow of data without record boundaries. Aside from the bidirectionality of data flow, a pair of connected stream sockets provides an interface nearly identical to pipes.

SOCK_RAW: Provides access to internal network protocols and interfaces. This type of socket is available only to users with root-user authority, or to non-root users who have the CAP_NUMA_ATTACH capability. (For non-root raw socket access, the chuser command assigns the CAP_NUMA_ATTACH capability, along with CAP_PROPAGATE. For further information, refer to the chuser command.)

Raw sockets allow an application to have direct access to lower-level communication protocols. Raw sockets are intended for advanced users who want to take advantage of some protocol feature that is not directly accessible through a normal interface, or who want to build new protocols on top of existing low-level protocols.

Raw sockets are normally datagram-oriented, though their exact characteristics are dependent on the interface provided by the protocol.

SOCK_SEQPACKET: Provides sequenced, reliable, and unduplicated flow of information.

SOCK_CONN_DGRAM: Provides connection-oriented datagram service. This type of socket supports the bidirectional flow of data, which is sequenced and unduplicated, but is not reliable. Because this is a connection-oriented service, the socket must be connected prior to data transfer. Currently, only the Asynchronous Transfer Mode (ATM) protocol in the Network Device Driver (NDD) domain supports this socket type.

它们是如何工作的?

SOCK_DGRAMSOCK_RAW套接字类型允许应用程序通过send子例程向命名的通信者发送数据报。应用程序可以使用recv子例程通过套接字接收数据报。当使用SOCK_RAW套接字类型与低级协议或硬件接口进行通信时,协议参数非常重要。应用程序必须指定通信所在的地址族。

这是使用SOCK_STREAM(TCP协议)套接字类型进行通信所需的一般函数调用序列:

SOCK_STREAM套接字类型是全双工字节流。在可以发送或接收任何数据之前,必须连接流套接字。当使用流套接字进行数据传输时,应用程序需要执行以下序列:

  1. 使用connect子例程与另一个套接字建立连接。
  2. 使用readwrite子例程或sendrecv子例程来传输数据。
  3. 使用close子例程结束会话。

应用程序可以使用sendrecv子例程来管理带外数据。

在使用 SOCK_STREAM 时,errno 可能返回或设置的错误:
通信协议 SOCK_STREAM 旨在防止数据的丢失或重复。如果一个数据块无法在合理的时间内成功传输,而对等协议有缓冲空间,则连接会断开。当发生这种情况时,socket 子程序返回值为 -1 并设置全局变量 errnoETIMEDOUT,表示出现错误。如果进程在已断开的流上发送数据,则会引发 SIGPIPE 信号。不能处理该信号的进程将终止。当套接字上收到带外数据时,将向进程组发送 SIGURG 信号。

与套接字关联的进程组可以通过 SIOCGPGRPSIOCSPGRP ioctl 操作进行读取或设置。要在任何数据上接收信号,请同时使用 SIOCSPGRPFIOASYNC ioctl 操作。这些操作在 sys/ioctl.h 文件中定义。

大概就是这样了。我希望很快在我的eRCaGuy_hello_world存储库的c dir中编写一些基本演示。

主要参考资料:

  1. [我的回答] Unix命令名后面括号中的数字代表什么意思?
  2. *****https://linux.die.net/man/7/ip
  3. https://linux.die.net/man/2/socket
  4. https://linux.die.net/man/7/tcp
  5. https://linux.die.net/man/7/udp
  6. int socket(AddressFamily, Type, Protocol) 函数:https://www.ibm.com/docs/en/aix/7.1?topic=s-socket-subroutine
  7. 地址族:https://www.ibm.com/docs/en/aix/7.1?topic=domains-address-families 和这里
  8. 套接字类型:https://www.ibm.com/docs/en/aix/7.1?topic=protocols-socket-types

相关:

  1. 什么是SOCK_DGRAMSOCK_STREAM
  2. 何时需要IPPROTO_UDP
  3. IPPROTO_IPIPPROTO_TCP/IPPROTO_UDP的区别

3
"SOCK_DGRAM 是 UDP... SOCK_STREAM 是 TCP" 这种说法在两方面都是不正确的。SOCK_DGRAM 是一个基于数据报的套接字,而使用的传输协议并不影响它的性质。UDP 是其中一种使用数据报的传输协议,但并不是唯一的一种。SOCK_STREAM 是一个基于流的套接字,同样也不受使用的传输协议影响。TCP 是其中一种使用流的传输协议,但同样也不是唯一的一种。socket() 函数的 protocol 参数决定了使用 UDP/TCP,而不是 type 参数。但是,只能在 SOCK_DGRAM 类型的套接字上使用 UDP,只能在 SOCK_STREAM 类型的套接字上使用 TCP。 - Remy Lebeau
1
那也是不正确的,因为UDP和TCP都支持AF_INET6。地址族决定了对等方如何寻址(IPv4 vs IPv6 vs ...),与套接字类型(数据报 vs 流 vs ...)或使用的协议(UDP vs TCP vs ...)无关。只有当套接字协议明确为IPPROTO_UDP时才使用UDP。只有当套接字协议明确为IPPROTO_TCP时才使用TCP。其他传输也是可能的(ICMP、IPX、RAW等)。 - Remy Lebeau
1
这仍然有点误导性。您真的需要区分套接字的类型和套接字使用的协议socket()可以做出这种区分。您的解释并没有很好地解决这个问题。而且,您仍然完全忽略了AF_INET6用于IPv6寻址。AF_INET用于IPv4寻址。 - Remy Lebeau
1
“TCP是由SOCK_STREAM使用的默认协议”是无意义的。 SOCK_STREAM只是API的选择器常量。该API没有“默认为SOCK_STREAMSOCK_DGRAM”的概念。也许在AF_X + SOCK_Y的情况下,您可以用默认值来表达,但这忽略了问题的要点。 - Błażej Michalik
1
不行,因为这些选择器的重点是API基于AF/SOCK矩阵进行选择。说“它是SOCK_XYZ的默认值”会使一个错误的想法持续存在,即在缺少AF_*时存在SOCK_*的默认值。 - Błażej Michalik
显示剩余7条评论

-6

TCP 使用 SOCK_STREAM,而 UDP 使用 SOCK_DGRAM。


1
所以你刚刚复制了第一个答案的第一行。请更具体地描述OP提出的问题。 - Abhishek Dutt
1
@Xenikh 没有,他正确地省略了荒谬的资格要求“几乎总是”。 - user207421

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