了解用于套接字编程的 INADDR_ANY

Posted

技术标签:

【中文标题】了解用于套接字编程的 INADDR_ANY【英文标题】:Understanding INADDR_ANY for socket programming 【发布时间】:2013-05-06 16:45:01 【问题描述】:

我正在尝试对一些套接字进行编程,因此在服务器端,我使用htonl(INADDR_ANY)。据我了解,在我看来,这个函数会生成一个随机 IP(我正确吗?)。事实上,我想将我的套接字与我的localhost 绑定。但是如果我运行这个

printf("%d",htonl(INADDR_ANY));

我得到 0 作为返回值。有人能解释一下吗?

【问题讨论】:

"...我使用htonl(INADDR_ANY)。文档说这个函数会生成一个随机IP..."这是不正确的。哪个文档告诉你的? @alk,实际上我误导了:我正在阅读一些我认为是一些官方文档的 pdf。我现在编辑我的帖子 【参考方案1】:

INADDR_ANY 用于不需要将套接字绑定到特定 IP 时。当你在调用bind()时使用这个值作为地址时,socket接受到本机所有IP的连接。

【讨论】:

【参考方案2】:

    bind() of INADDR_ANY 确实 “生成随机 IP”。它binds the socket to all available interfaces。

    对于服务器,您通常希望绑定到所有接口 - 而不仅仅是“localhost”。

    如果您只想将套接字绑定到 localhost,则语法为 my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1");,然后调用 bind(my_socket, (SOCKADDR *) &my_sockaddr, ...)

    碰巧,INADDR_ANY 是一个恰好等于“零”的常量:

    http://www.castaglia.org/proftpd/doc/devel-guide/src/include/inet.h.html

    # define INADDR_ANY ((unsigned long int) 0x00000000)
    ...
    # define INADDR_NONE    0xffffffff
    ...
    # define INPORT_ANY 0
    ...
    

    如果您还不熟悉它,我建议您查看 Beej 的套接字编程指南:

    http://beej.us/guide/bgnet/

由于人们仍在阅读本文,因此补充说明:

man (7) ip:

当一个进程想要接收新的传入数据包或连接时, 它应该使用bind(2) 将套接字绑定到本地接口地址。

在这种情况下,只有一个 IP 套接字可以绑定到任何给定的本地 (地址,端口)对。在绑定调用中指定 INADDR_ANY 时, 套接字将绑定到所有本地接口。

当listen(2)在一个未绑定的socket上被调用时,这个socket是 自动绑定到具有本地地址集的随机空闲端口 到 INADDR_ANY。

当connect(2)在一个未绑定的socket上被调用时,这个socket是 自动绑定到一个随机的空闲端口或一个可用的共享端口 本地地址设置为 INADDR_ANY...

有几个特殊地址:INADDR_LOOPBACK (127.0.0.1) 总是通过环回设备引用本地主机; INADDR_ANY (0.0.0.0) 表示任意绑定地址...

还有:

bind() — Bind a name to a socket:

如果 (sin_addr.s_addr) 字段设置为常量 INADDR_ANY,如 在 netinet/in.h 中定义,调用者请求套接字是 绑定到主机上的所有网络接口。随后,UDP数据包 和来自所有接口的 TCP 连接(与绑定名称匹配) 被路由到应用程序。当服务器时,这变得很重要 为多个网络提供服务。通过留下地址 未指定,服务器可以接受所有 UDP 数据包和 TCP 连接 对其端口发出的请求,无论网络接口如何 请求到达的位置。

【讨论】:

这并不意味着“绑定到所有接口”。如果这样做,netstat 输出将有所不同。意思是“在任何界面收听”。 引用上面的链接:“当绑定调用中指定了 INADDR_ANY 时,套接字将绑定到所有本地接口。”来自另一个链接:The value "INADDR_ANY" means that we will bind to any/all IP addresses that the local computer currently has。但是是的 - 许多实现将绑定到 第一个 接口,(不是“全部”)。但是对于一台带有一个 NIC 的 PC,区别是学术性的。使用 INADDR_ANY,客户端可以连接到任何/所有 IP(例如 192.168.1.2 和 127.0.0.1)。 对不起,这是一个愚蠢的问题,但是接口是指无线、以太网等吗? @laike9m 当您希望只能从本地计算机连接到套接字时,您将绑定到 127.0.0.1。当套接字提供的服务仅打算由机器本地的另一个进程使用时,有一些用例。 @paulsm4 在3中,你不能用INADDR_LOOPBACK,而不是inet_addr("127.0.0.1")吗?【参考方案3】:

为了bindlocalhost 的socket,在你调用bind 函数之前,sockaddr_in 结构的sin_addr.s_addr 字段应该被正确设置。正确的值可以通过

my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1")

或通过

my_sockaddress.sin_addr.s_addr=htonl(INADDR_LOOPBACK);

【讨论】:

【参考方案4】:

INADDR_ANY 是一个常量,它的 value 包含 0。仅当您想从您不关心的所有活动端口连接时才会使用 ip-add 。 所以如果你想连接任何特定的IP,你应该提到像 my_sockaddress.sin_addr.s_addr = inet_addr("192.168.78.2")

【讨论】:

【参考方案5】:

INADDR_ANY 指示侦听套接字绑定到所有可用接口。这与尝试绑定到inet_addr("0.0.0.0") 相同。 为了完整起见,我还要提到 IPv6 也有 IN6ADDR_ANY_INIT,这与尝试绑定到 IPv6 套接字的 :: 地址相同。

#include <netinet/in.h>

struct in6_addr addr = IN6ADDR_ANY_INIT;

另外,请注意,当您将 IPv6 套接字绑定到 IN6ADDR_ANY_INIT 时,您的套接字将绑定到所有 IPv6 接口,并且也应该能够接受来自 IPv4 客户端的连接(尽管是 IPv6 映射地址)。

【讨论】:

【参考方案6】:

当您拥有一个服务器时,您创建一个套接字,然后将其绑定到一个 IP 和端口,这为套接字提供了一种基于唯一套接字类型、地址族、IP 和端口的唯一识别方式。然后用listen() 将套接字设置为服务器模式,然后执行accept(),它会等待一个连接,该连接将包含带有目标参数的入站数据包,这些参数会导致数据包在该套接字上排队。

当你有一个客户端时,你创建一个套接字,然后你 connect() 套接字到一个远程 IP 和端口,如果它没有,它也会将 0.0.0.0 和一个随机未使用的临时端口绑定到套接字已经使用 bind(INADDR_ANY, 0) 绑定到 IP 和端口。 connect() 连接时返回,并在出站数据包中使用 IP 和端口作为源地址,其中 0.0.0.0 总是被操作系统替换为当前内部 IP,然后您使用 sendall 发送应用程序数据。

INADDR_ANY 比以编程方式获取计算机的当前内部 IP 更快,后者可能随时更改,并且将不再在端口上接收数据包,但仍会在 0.0.0.0 上接收它们,因为它是任何地址。

请注意,套接字可以绑定到 0.0.0.0,但不能绑定到端口 0,因为它是一个通配符,可以为套接字提供一个随机的临时端口,所以当您使用 bind(INADDR_ANY, 0) 时,它会绑定到 0.0。 0.0 和一个随机的临时端口。

【讨论】:

【参考方案7】:
#include <arpa/inet.h>                                                                     
.                                                                                   
.                                                                                        
tcpsock.sin_addr.s_addr = inet_addr("192.168.1.2")

为我工作

【讨论】:

以上是关于了解用于套接字编程的 INADDR_ANY的主要内容,如果未能解决你的问题,请参考以下文章

网络编程套接字

使用INADDR_ANY的目的和结果是什么?

ioctl() 用于 C 中的套接字编程

基于套接字的通信独立于用于实现它的编程语言。这怎么可能? [关闭]

在 WinSock 中通过 127.0.0.1 发送的多播可以用 INADDR_ANY 读取吗?

LinuxSocket套接字编程基础