【问题标题】:Unable to connect 2 machines using ipv6 (TCP server client )无法使用 ipv6 连接 2 台机器(TCP 服务器客户端)
【发布时间】:2012-10-28 06:45:34
【问题描述】:

我正在尝试使用 ipv6 做一个简单的 tcp 服务器客户端。它适用于 ipv6 和 ipv4 的同一台机器,但在不同的机器上时,ipv6 无法连接。

服务器代码

int main(int argc, char* argv[])
{
    int sockfd,new_fd,rv,yes=1; 
    struct addrinfo hints,*servinfo,*p; 
    struct sockaddr_storage their_addr;
    socklen_t addr_size;

    SOCKET listenSocket,clientSocket;
    WSADATA w;

    if (WSAStartup(0x0101, &w) != 0)
    {
        fprintf(stderr, "Could not open Windows connection.\n");
        exit(0);
    }

    //ip=argv[1];
    //port=argv[2];

    memset(&hints,0,sizeof(hints));

    hints.ai_family=AF_INET6;
    hints.ai_socktype=SOCK_STREAM;  
    hints.ai_flags=AI_NUMERICHOST;

    if((rv = getaddrinfo("fe80::c0a8:0160","5002",&hints,&servinfo)) != 0)
    {
        perror("\nGetaddrinfo failed\n");
        return 1;
    }   

    //Creating socket   
    listenSocket = socket(servinfo->ai_family,servinfo->ai_socktype,servinfo->ai_protocol);

    if(listenSocket == INVALID_SOCKET)
    {
        printf("\nSocket failed with error \n");
        WSACleanup();
    }

    //setting non blocking mode
    u_long iMode = 1;
    rv = ioctlsocket(listenSocket,FIONBIO,&iMode);

    if(rv == SOCKET_ERROR)
    {
        printf("\nioctl failed\n");
        WSACleanup();
    }

    rv = bind(listenSocket,servinfo->ai_addr,(int)servinfo->ai_addrlen);

    if(rv == SOCKET_ERROR)
    {
        perror("\nBind: \n");
    }

    freeaddrinfo(servinfo);

    rv = listen(listenSocket,SOMAXCONN);

    if(rv == SOCKET_ERROR)
    {
        perror("listen");
        return 1;
    }

    // now accept an incoming connection:


    char recvbuf[DEFAULT_BUFLEN];
    int buflen = DEFAULT_BUFLEN;
    SOCKET AcceptSocket;

    while (1)
    {
        AcceptSocket = SOCKET_ERROR;

        while (AcceptSocket == SOCKET_ERROR)
        {
            AcceptSocket = accept(listenSocket, NULL, NULL);
        }

        printf("Server: Client Connected!\n");
        listenSocket = AcceptSocket;

        rv = recv(listenSocket,recvbuf,buflen,0);
        break;
    }


    printf("Received %d bytes from client \n",rv);  

    closesocket(listenSocket);
    closesocket(AcceptSocket);

    return 0;

}

客户端代码

int main(int argc,char* argv[])
{
    struct addrinfo hints,*servinfo,*p;
    int rv;
    SOCKET connectSocket;
    WSADATA w;

    if (WSAStartup(0x0101, &w) != 0)
    {
        fprintf(stderr, "Could not open Windows connection.\n");
        exit(0);
    }

    //resetting memory
    memset(&hints,0,sizeof(hints));

    hints.ai_family = AF_INET6;
    hints.ai_socktype = SOCK_STREAM;    
    hints.ai_flags = AI_NUMERICHOST;

    //getting values

    if((rv = getaddrinfo("fe80::c0a8:160","5002",&hints,&servinfo)) != 0)
    {
        perror("Getaddrinfo failed");
        return 1;
    }

    //Creating socket
    connectSocket = socket(servinfo->ai_family,servinfo->ai_socktype,servinfo->ai_protocol);

    if(connectSocket == INVALID_SOCKET)
    {
        perror("Socket create : ");
    }

    rv = connect(connectSocket,servinfo->ai_addr,(int)servinfo->ai_addrlen);
    if(rv == SOCKET_ERROR)
    {
        perror("Socket Connect : ");
    }


    //free memory
    freeaddrinfo(servinfo);


    // Send and receive data.
    int bytesSent;

    char sendbuf[200] = "Client: Sending some test string to server...";
    char recvbuf[200] = "";

    bytesSent = send(connectSocket, sendbuf, strlen(sendbuf), 0);
    printf("Client: send() - Bytes Sent: %ld\n", bytesSent);

    closesocket(connectSocket);
    return 0;
}

目的只是打印传输了多少字节。

【问题讨论】:

  • 正如 shinkou 回答的那样,您绑定到链接本地地址。另一个问题是您绑定到一个静态地址,该地址在具有该地址的计算机上工作,但在没有这个确切地址的任何计算机上都不能工作。我建议绑定到IN6ADDR_ANY_INIT,它绑定到所有接口,以便服务器可以连接到计算机拥有的所有地址。
  • @JoachimPileborg 我已经为机器分配了一个静态 ipv6。两台机器之间的 Ping 也工作正常。
  • 你把代码中的地址移到另一台机器上的时候改了?还是两台机器地址相同?
  • @JoachimPileborg 都分配了不同的地址,我也在代码中更改了它。 :)

标签: c ipv6


【解决方案1】:

您使用的似乎是link local address。你确定吗?另外,我建议您先检查您的防火墙设置。

编辑: 尝试包含区域 ID。当您在命令提示符下发出ipconfig 时,您应该能够获得类似fe80::c0a8:0160%21 的地址,其中%21 是区域ID。根据this answer使用link local addresses时很重要。

【讨论】:

  • 不,它不是链接本地地址。我手动分配了上面使用的IP地址。事实上,我分配了一个转换后的静态 ipv4。为家庭网络启用防火墙,为公共网络禁用防火墙。使用的机器在同一个本地网络中。
  • 是的,是链接本地地址。每个以 fe80: 开头的地址都是本地链接。对于这样的测试,您可以使用从 ISP 获得的地址,也可以使用 ULA (sixxs.net/tools/grh/ula) 地址。如果您真的想使用链接本地地址,则必须明确指定要在其上使用它们的接口。毕竟它们是本地链接:)
  • @Kols 是链接本地地址,但是由于两台机器在同一个网段,应该可以的。
  • @SanderSteffann 我认为本地链接是为 eth0 自动设置的链接。例如 fe80::b8e1:d4bb:cbe4:f764%10 。目前我的 ISP 不支持 ipv6。但我的目标只是连接同一网络中的两台机器,它们将被分配 ipv6 地址(静态)。我必须检查它是否适用于自动生成的 ipv6(具有指定接口)。这仍然不是我要找的东西。 :) shinkou 我会重新检查机器的任何 ipv6 兼容性问题。
  • @Kols 这对我来说听起来像是防火墙。您是否尝试过禁用防火墙设置,不是在路由器上,而是在机器上?
猜你喜欢
  • 1970-01-01
  • 2017-02-24
  • 2015-08-21
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
  • 2011-04-09
相关资源
最近更新 更多