套接字编程中,AF_INET和PF_INET有什么区别?

256

socket编程中,AF_INET与PF_INET有什么区别?

我在使用socket()bind()时对使用AF_INET和PF_INET感到困惑。

此外,在sin_addr字段中如何指定IP地址?


只需在网上搜索:一个结果是这个 - Op De Cirkel
我也一直在想这个问题。它们似乎在不同的编码人员中在套接字调用中可以互换使用。 - hookenz
@MattH 根据新的Linux内核,它们是相同的。您可以在Duke的下面答案中找到相同的内容。 - SP Sandhu
7个回答

302

Beej's网络编程指南提供了一个很好的解释:

在一些文档中,你会看到对“PF_INET”这个神秘的东西的提及。这是一个奇怪的、罕见的存在,但我可以在这里澄清一下。很久以前,有人认为一个地址家族(“AF_INET”中的“AF”代表什么)可能支持多个协议,这些协议由它们的协议家族(“PF_INET”中的“PF”代表什么)引用。
没有发生。好吧。所以,在你的 struct sockaddr_in 中使用 AF_INET,在调用 socket()时使用 PF_INET 是正确的做法。但实际上,你可以在所有地方使用 AF_INET。而且,既然 W. Richard Stevens 在他的书中都这样做了,那我在这里也会这样做。


90

我在 Linux 内核源代码中发现 PF_INET 和 AF_INET 是相同的。 以下代码来自于文件 include/linux/socket.h,是 Linux 内核 3.2.21 树的第204行。

/* Protocol families, same as address families. */
...
#define PF_INET     AF_INET

杜克,之前的内核也是这样吗?我是说在3.0版本之前的内核? - SP Sandhu
4
据我所知,在所有内核和libc版本中,PF_* == AF_*。 - Duke
非 Linux 平台上是否也是如此? - Good Person
2
我认为为了确保,你需要检查所包含的头文件 :) - Duke
1
在Ubuntu/Debian中,我发现AF定义在/usr/src/linux-headers-<kernel_version>/include/linux/socket.h中。 - Petr Javorik

60
  • AF = 地址族
  • PF = 协议族

即,AF_INET 指的是来自 Internet 的地址,具体指 IP 地址。 PF_INET 指的是协议中的任何内容,通常是套接字/端口。

建议阅读 socket(2)bind(2) 的 man 手册。对于 sin_addr 字段,只需像以下示例那样设置:

struct sockaddr_in addr;
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr); 

谢谢@codemac,我已经使用了addr.sin_addr.s_addr = inet_addr("127.0.0.1");但inet_pton()是用来做什么的? - SP Sandhu
还有关于 man 手册页的问题,当我输入 man bind(2) 或者 man bind() 时,终端会给出意外的标记 '(' 错误,而 man bind 则解释了 bash 内置的 bind。如何获取 bind() 函数的 man 手册页? - SP Sandhu
@jatt.beas:语法是 man <section> <topic>,例如 man 2 bind - Frerich Raabe

15
事实上,AF_和PF_是相同的东西。维基百科上有一些词语可以澄清你的困惑。
原始设计概念中,套接字接口区分协议类型(族)和每个协议类型可能使用的特定地址类型。设想一个协议族可能有几种地址类型。地址类型是通过使用前缀AF_而不是PF_来定义的附加符号常量。AF_-标识符适用于所有专门处理地址类型而不是协议族的数据结构。然而,这种协议和地址类型分离的概念没有得到实现支持,AF_-常量仅由相应的协议标识符定义,使得AF_与PF_常量之间的区别成为没有重要实际后果的技术争论。实际上,在正确使用这两种形式方面存在很多混淆。

8

AF_INET代表地址格式,Internet代表IP地址。

PF_INET代表数据包格式,Internet代表IP、TCP/IP或UDP/IP。

在创建套接字时使用的地址族是AF_INET(在本例中为Internet协议地址)。例如,Linux内核支持其他29个地址族,如UNIX套接字和IPX,还支持与IRDA和蓝牙通信(AF_IRDA和AF_BLUETOOTH),但很难在这个低级别上使用它们。

大多数情况下,在网络套接字编程中坚持使用AF_INET是最安全的选择。

也就是说,AF_INET指的是来自互联网的地址,特别是IP地址。

PF_INET指的是协议中的任何内容,通常是套接字/端口。


必须指出的是,AF/PF的正确扩展应为“地址/数据包”(与其他答案相同),而不是您在此处提供的“格式”。我意识到你很可能一直知道这一点,并故意选择了(技术上不正确的)扩展“格式”,因为你认为它比“族”具有教育优势-你可能是对的,但如果这是你的理由,最好明确说明,这样人们就不会错误地认为“地址/协议格式”是正确的术语。 - Simon Kissane
@SimonKissane 您是不是指的是“协议族”而不是“数据包族”? - Torin
@Torin 是的,你是对的。我指出了“格式”部分是错误的,但“数据包”部分也是错误的。我第二次说得对,第一次在没有注意到时复制了答案的错误。 - Simon Kissane

7

检查头文件可以解决问题。

可以检查系统编译器。

对于我的系统,AF_INET == PF_INET

AF == 地址族 且 PF == 协议族

协议族与地址族相同。

enter image description here


2
/usr/src/linux-headers-X.X.X-XX-generic/include/linux/socket.h - noobninja

1

有些情况很重要。

如果在Cygwin中将AF_INET传递给socket(),则您的套接字可能会随机重置。传递PF_INET可以确保连接正常工作。

Cygwin自认为是套接字编程的一个混乱,但这是一个真实世界的例子,其中AF_INET和PF_INET不相同。


15
请解释一下。我在Cygwin的socket.h文件中找到了#define PF_INET AF_INET的代码。 - user207421
我认为这个答案是错误的。在Cygwin中,"PF_INET=AF_INET"。无论如何,Cygwin只是Winsock2的一层,其中也有"PF_INET=AF_INET"。有时候一个人遇到一个他们不理解的奇怪问题,当他们改变了某些东西时问题就消失了,这会让他们相信改变解决了问题 - 而实际上这个变化是一个没有意义的操作,问题巧合地因为其他原因而消失了。我猜想这就是导致你产生这个错误信念的原因。据我所知,在所有真实的系统中,对于所有的X值,PF_X=AF_X。 - Simon Kissane

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