关于INADDR_ANY的问题

常量INADDR_ANY是所谓的IPv4通配符地址。 通配符IP地址对于绑定多宿主主机上的Internet域套接字的应用程序非常有用。 如果多宿主主机上的应用程序将套接字绑定到其主机的一个IP地址,则该套接字只能接收发送到该IP地址的UDP数据报或TCP连接请求。 但是,我们通常希望多宿主主机上的应用程序能够接收指定任何主机IP地址的数据报或连接请求,并将套接字绑定到通配符IP地址使之成为可能。

struct sockaddr_in server_address; int server_sockfd = socket(AF_INET, SOCK_STREAM, 0); memset(&server_address, 0, sizeof(struct sockaddr_in)); server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = htonl(INADDR_ANY); // here is my quesion server_address.sin_port = htons(9734); bind(server_sockfd, (struct sockaddr*)&server_address, sizeof(server_address)); 

问>

如果我们将套接字绑定到特定的IP地址,那么套接字只能接收发送给该IP地址的UPD / TCP请求。

正如我在上面的代码所示,现在套接字server_sockfd绑定INADDR_ANY。 如果套接字可以在互联网上接收到任何请求,那么我只是感到困惑在这里B / C如何仍然可以正常工作。 在互联网上有大量的UDP / TCP请求,如果套接字响应每个人,它又怎么能工作?

//更新客户端的代码//

 int main(int argc, char *argv[]) { struct sockaddr_in6 svaddr; int sfd, j; size_t msgLen; ssize_t numBytes; char resp[BUF_SIZE]; if (argc < 3 || strcmp(argv[1], "--help") == 0) usageErr("%s host-address msg...\n", argv[0]); /* Create a datagram socket; send to an address in the IPv6 somain */ sfd = socket(AF_INET6, SOCK_DGRAM, 0); /* Create client socket */ if (sfd == -1) errExit("socket"); memset(&svaddr, 0, sizeof(struct sockaddr_in6)); svaddr.sin6_family = AF_INET6; svaddr.sin6_port = htons(PORT_NUM); if (inet_pton(AF_INET6, argv[1], &svaddr.sin6_addr) <= 0) fatal("inet_pton failed for address '%s'", argv[1]); /* Send messages to server; echo responses on stdout */ for (j = 2; j < argc; j++) { msgLen = strlen(argv[j]); if (sendto(sfd, argv[j], msgLen, 0, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_in6)) != msgLen) fatal("sendto"); numBytes = recvfrom(sfd, resp, BUF_SIZE, 0, NULL, NULL); if (numBytes == -1) errExit("recvfrom"); printf("Response %d: %.*s\n", j - 1, (int) numBytes, resp); } exit(EXIT_SUCCESS); } 

/ /更新服务器端代码

 int main(int argc, char *argv[]) { struct sockaddr_in6 svaddr, claddr; int sfd, j; ssize_t numBytes; socklen_t len; char buf[BUF_SIZE]; char claddrStr[INET6_ADDRSTRLEN]; /* Create a datagram socket bound to an address in the IPv6 somain */ sfd = socket(AF_INET6, SOCK_DGRAM, 0); if (sfd == -1) errExit("socket"); memset(&svaddr, 0, sizeof(struct sockaddr_in6)); svaddr.sin6_family = AF_INET6; svaddr.sin6_addr = in6addr_any; /* Wildcard address */ svaddr.sin6_port = htons(PORT_NUM); if (bind(sfd, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_in6)) == -1) errExit("bind"); /* Receive messages, convert to uppercase, and return to client */ for (;;) { len = sizeof(struct sockaddr_in6); numBytes = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len); if (numBytes == -1) errExit("recvfrom"); /* Display address of client that sent the message */ if (inet_ntop(AF_INET6, &claddr.sin6_addr, claddrStr, INET6_ADDRSTRLEN) == NULL) printf("Couldn't convert client address to string\n"); else printf("Server received %ld bytes from (%s, %u)\n", (long) numBytes, claddrStr, ntohs(claddr.sin6_port)); for (j = 0; j < numBytes; j++) buf[j] = toupper((unsigned char) buf[j]); if (sendto(sfd, buf, numBytes, 0, (struct sockaddr *) &claddr, len) != numBytes) fatal("sendto"); } } 

//更新了如何运行这个服务器/客户端程序。

 $ ./server_program & [1] 31047 $ ./client_program ::1 ciao // Send to server on local host Server received 4 bytes from (::1, 32770) Response 1: CIAO 

它不会获取互联网上每个IP地址的请求(a) ,它将获取它所服务的每个IP地址的请求。 例如,它可能有多个NIC,每个NIC都有一个单独的IP地址,或者它可能有一个能够管理多个IP地址的NIC(甚至可能有多个NIC,每个NIC都能够处理多个IP地址。

要看的关键片段是:

…我们通常希望多宿主主机上的应用程序能够接收指定任何主机IP地址 (我的斜体)的数据报或连接请求。

换句话说,您的机器服务器10.0.0.1510.0.0.16可能有多宿主设置。 使用INADDR_ANY将允许您为这两个地址获取流量, 而不会提取10.0.0.17请求,这可能是板凳另一端(或地球另一端)的机器。

下表中,首行是请求目标,左列是您正在侦听的地址,显示您是否会收到请求( Y )或不是( N ):

 Request to> 10.0.0.15 10.0.0.16 10.0.0.17 Bind to: *------------------------------- 10.0.0.15 | YNN 10.0.0.16 | NYN INADDR_ANY | YYN 

(a)甚至没有看到绝大多数网上的请求。 绝大多数甚至没有到最近的路由器(甚至可能是你的ISP)。 即使是那些做到最近的路由器,你的特定机器可能不会看到它们是否注定要在本地网段上的另一台机器上(混杂模式尽管)。