98

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

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

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

4

7 回答 7

162
  1. bind()ofINADDR_ANY不会“生成随机 IP” 它将套接字绑定到所有可用的接口

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

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

  4. 碰巧,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
    ...
    
  5. 如果您还不熟悉它,我强烈建议您查看 Beej 的套接字编程指南:

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

由于人们仍在阅读此内容,因此请注意:

人 (7) ip :

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

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

当在未绑定的套接字上调用listen(2)时,该套接字会自动绑定到一个随机空闲端口,其本地地址设置为 INADDR_ANY。

当在未绑定的套接字上调用connect(2)时,套接字会自动绑定到随机空闲端口或本地地址设置为 INADDR_ANY 的可用共享端口...

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

还:

bind() — 将名称绑定到套接字

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

于 2013-05-12T17:11:12.443 回答
66

INADDR_ANY当您不需要将套接字绑定到特定 IP 时使用。当您在调用时将此值用作地址时bind(),套接字接受与机器所有 IP 的连接。

于 2013-05-12T15:17:49.487 回答
10

要将套接字与localhost绑定,在调用绑定函数之前,应正确设置 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);
于 2013-08-15T10:35:08.873 回答
6

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 映射地址)。

于 2018-05-11T05:52:03.087 回答
2

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

于 2017-07-12T07:53:37.127 回答
2

当你有一个服务器时,你创建一个套接字,然后将它绑定到一个 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 和随机临时端口。

于 2021-06-08T07:43:17.207 回答
0
#include <arpa/inet.h>                                                                     
.                                                                                   
.                                                                                        
tcpsock.sin_addr.s_addr = inet_addr("192.168.1.2")

为我工作

于 2021-11-21T10:59:29.280 回答