AF_INET和PF_INET常量有什么区别?

35 投票
1 回答
20515 浏览
提问于 2025-04-15 21:03

在查看关于套接字编程的例子时,我们会发现有些人使用 AF_INET,而另一些人则使用 PF_INET。有时候,甚至在同一个例子中会同时出现这两者。那么,它们之间有什么区别呢?我们应该使用哪个呢?

如果你能回答这个问题,接下来还有一个问题... 为什么会有这两个相似(但不完全相同)的常量呢?


到目前为止我发现的:

socket 手册

在(Unix)套接字编程中,我们有一个 socket() 函数,它接收以下参数:

int socket(int domain, int type, int protocol);

手册中提到:

domain 参数指定了一个通信域;这选择了将用于通信的协议族。这些族在 <sys/socket.h> 中定义。

手册中提到 AF_INET 以及其他一些 AF_ 常量作为 domain 参数。此外,在同一手册的 NOTES 部分,我们可以看到:

在 4.x BSD 中用于协议族的常量是 PF_UNIX、PF_INET 等,而 AF_UNIX 等则用于地址族。然而,BSD 手册已经承诺:“协议族通常与地址族相同”,后来的标准在各处使用 AF_*。

C 头文件

sys/socket.h 实际上并没有定义这些常量,而是包含了 bits/socket.h。这个文件定义了大约 38 个 AF_ 常量和 38 个 PF_ 常量,如下所示:

#define PF_INET     2   /* IP protocol family.  */
#define AF_INET     PF_INET

Python

Python 的套接字模块 与 C 的 API 非常相似。不过,Python 中有很多 AF_ 常量,但只有一个 PF_ 常量(PF_PACKET)。因此,在 Python 中我们只能使用 AF_INET

我认为这个只包含 AF_ 常量的决定遵循了一个指导原则:“应该有一种——最好只有一种——明显的方法来做到这一点。” (Python 的禅)

其他信息

这个论坛帖子 链接到 这条旧消息,其中包含一些历史信息。

1 个回答

28

我觉得维基百科上的说明总结得很好:

最初设计socket接口的时候,区分了协议类型(家族)和每种协议可以使用的具体地址类型。想象一下,一个协议家族可能会有好几种地址类型。地址类型是通过一些额外的符号常量来定义的,这些常量用前缀AF_来表示,而不是PF_AF_的标识符是专门用于处理地址类型的数据结构,而不是协议家族。不过,这种将协议和地址类型分开的概念并没有得到实际的支持,AF_常量实际上是根据相应的协议标识符来定义的,这样一来,AF_PF_常量之间的区别就变成了一个技术上的争论,而在实际应用中并没有太大的意义。实际上,很多人对这两种形式的正确使用感到困惑。

即使今天有人想出一个理由来区分这两者,他们也得想出新的标识符,否则很多东西都会出问题……

撰写回答