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):
- 我不知道 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,它大多是退化的。