当前位置: 首页 > 面试题库 >

关于INADDR_ANY的问题

邓光耀
2023-03-14
问题内容

常量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绑定。如果套接字可以在互联网上收到任何请求,我仍然感到困惑,因为它仍然可以正常工作。互联网上有大量的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

问题答案:

它不会获取对Internet
(a)上每个IP地址的请求,而是会获取其服务的每个IP地址的请求。例如,它可能具有多个NIC,每个NIC都有一个单独的IP地址,或者它可能具有一个能够管理多个IP地址的NIC(它甚至可能具有多个NIC,每个NIC能够处理多个IP地址。

要查看的关键代码段是:

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

换句话说,您可能有一个多宿主设置,其中您的机器服务10.0.0.1510.0.0.16。使用,INADDR_ANY您可以选择这两个地址的流量,
而无需 选择10.0.0.17可能是工作台另一端(或地球另一侧)上的计算机的请求。

下表中的第一行是请求的目的地,左列是您正在监听的地址,该表格显示了是否会向您发送请求YN):

Request to>  10.0.0.15  10.0.0.16  10.0.0.17
Bind to:    *-------------------------------
10.0.0.15   |    Y          N          N
10.0.0.16   |    N          Y          N
INADDR_ANY  |    Y          Y          N

(a)甚至在网络上都 看不到 绝大多数请求。绝大多数人甚至都没有将它连接到最近的路由器(甚至可能是您的ISP)。即使是那些 确实连接
到您最近的路由器的计算机,您的特定计算机也可能看不到它们是否是发往本地网段上的另一台计算机的(尽管是混杂模式)。



 类似资料:
  • 有时我们会遇到几个关于Autoconf的问题。下面是被提及的一些问题。 发布configure脚本 对发行由Autoconf生成的configure有什么限制?它们是如何影响我那些使用它们的程序的? 关于由Autoconf生成的配置脚本是如何发行和如何被使用的,并没有限制。在Autoconf第1版中,它们是服从GNU通用公共许可证的。 我们仍然鼓励软件的作者按照诸如GPL的条款发行他们的作品,但A

  • 问题内容: 我想查询在以下情况下flush方法的实际作用: 这是否意味着在迭代20之后,将刷新高速缓存,然后将这20个保留的内存对象实际保存在数据库中? 有人可以告诉我当条件为真时会发生什么。 问题答案: 来自的javadoc : 强制刷新该会话。必须在提交事务并关闭会话之前在工作单元的末尾调用(取决于 flush- mode ,Transaction.commit() 调用此方法)。 刷新 是将

  • 过去几天我一直在使用java,最近几天我收到了一个问题表单。当我试图在servlet中创建一个类时,包部分显示以下错误"** > 无法解析ObjectInputStreamjava.io.类型。它是从必需的. class文件间接引用的 当我试着评论出 导入javax.servlet.http.HttpServlet; **"部分的错误是去,但我不能扩展的http的servlet类。 此图像显示错误

  • 我们基本上是在使用这里记录的Git流:http://nvie.com/posts/a-successful-git-branching-model/.现在开发人员提出了一些问题: 我们从哪里发布代码到生产?发布/修补程序分支还是主分支 我还有更多问题: 如果发布分支没有变化,为什么我们甚至需要一个?我来自ClearCase世界,我总是有这样的印象,如果没有变化,分支就不需要了。 为什么Git不经常

  • 我需要你的帮助我是一个begineer在Spring启动,所以我有一个问题在Spring启动分页 存储库:

  • 想改进这个问题吗?更新问题,使其仅通过编辑这篇文章来关注一个问题。 刚开始学习java大约一个月,我对arraylist和oop有几个问题 这个arraylist允许我将字符串添加到列表中并存储它,但是如果我有一个类调用簿呢 这三者有什么区别?假设我有大量的输入,比如文件 我有一个班级运动 我该怎么做呢?所以我用许多参数来添加这些输入,因为如果我想添加,我通常会这样做 我也会去