【问题标题】:Why can I bind this socket to ::1%2 when ::1 is on interface 1?当 ::1 在接口 1 上时,为什么我可以将此套接字绑定到 ::1%2?
【发布时间】:2015-01-03 01:54:03
【问题描述】:

我试图了解sin6_scope_id 如何在 UNIX C 套接字编程中用于 IPv6 地址。具体来说,我编写了这个程序,它试图绑定到::1%2(如果我猜对了,就是接口 2 上的环回地址),即使我的环回地址实际上在接口 1 上。

我希望这会失败。但它绑定成功。为什么?

这是ifconfig -a返回的前3个接口:

$ ifconfig -a

lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    options=3<RXCSUM,TXCSUM>
    inet6 ::1 prefixlen 128
    inet 127.0.0.1 netmask 0xff000000
    inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
    nd6 options=1<PERFORMNUD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280

你可以编译这个程序:

cc -Wall -Wextra main.c

以下是注释来源:

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    // Allow any IP address on the interface with scope ID of 2.
    const char *hostname = "::1%2";

    // Say we want to bind on port 80 (for http).
    const char *servname = "1337";

    // Store some information about the IP address wanted.
    struct addrinfo hints;

    // Save addresses in here.
    struct addrinfo *addr_list_item = NULL;

    // Tell `getaddrinfo` that we want an address for IPv6 TCP.
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_INET6;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    if (getaddrinfo(hostname, servname, &hints, &addr_list_item) != 0) {
        printf("Could not read addresses.\n");
        exit(1);
    }

    // Create a socket and bind it to the address we found before. This should fail
    // but for some reason I don't understand it doesn't.
    if (addr_list_item) {
        int sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
        if (sock != -1) {
            if (bind(sock, addr_list_item->ai_addr, addr_list_item->ai_addrlen) != -1) {
                printf("Binded succesfully!\n");
            } else {
                perror(NULL);
            }
            close(sock);
        }
    }

    // Release memory.
    freeaddrinfo(addr_list_item);

    return (0);
}

【问题讨论】:

  • 也许它是特定于操作系统的 - 你在什么操作系统上运行?
  • 这是在 Linux 上,如果我没记错的话(抱歉我的回复延迟)。

标签: c unix tcp


【解决方案1】:

根据您的 unix 版本,%2 可能会被忽略。

在某些IBM systems 上,文档说:

上述 IPv6 文本形式可能包括附加区域指示符(如果前面有 % 字符)和/或附加前缀长度(如果前面有 / 字符)。在这些情况下,% 或 / 将被视为空终止符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多