2012-11-08 87 views
1

我试图做一个简单的tcp服务器客户端使用ipv6。它在ipv6和ipv4的同一台机器上工作,但是在不同的机器上ipv6无法连接。无法使用ipv6连接2台计算机(TCP服务器客户端)

服务器代码

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; 
} 

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

+0

正如shinkou回答的那样,你绑定到一个链接本地地址。另一个问题是你绑定到一个静态地址,该静态地址在计算机上工作,它具有该地址,但不适用于任何没有这个确切地址的计算机。我建议绑定到绑定到所有接口的'IN6ADDR_ANY_INIT',以便服务器可以连接到计算机所有的地址上。 –

+0

@JoachimPileborg我已经为机器分配了一个静态ipv6。还有两台机器之间的ping工作正常。 – Antarus

+0

当你把它移动到另一台机器时,你在代码中改变了地址?或者_both_机器具有相同的地址? –

回答

3

看起来您正在使用link local address。你确定吗?另外,我建议你先检查你的防火墙设置。编号: 尝试包含区域ID。当您在命令提示符下发出ipconfig时,您应该能够获得像fe80::c0a8:0160%21这样的地址,其中%21是区域ID。根据this answer,使用link local addresses时很重要。

+0

不,这不是链接本地地址。我已经手动分配了上面使用的IP地址。实际上我分配了一个转换后的静态ipv4。防火墙针对家庭网络启用并禁用公共网络。所使用的机器位于同一本地网络中。 – Antarus

+0

是的,它是一个链接本地地址。每个以fe80开头的地址都是本地链接。对于像这样的测试,您可以使用从ISP获得的地址,也可以使用ULA(http://www.sixxs.net/tools/grh/ula/)地址。如果您确实想使用链接本地地址,则必须明确指定要使用它们的接口。他们本地链接本地:) –

+0

@Kols这是一个链接本地地址,但由于两台机器驻留在同一个网段,它应该工作。 – shinkou

相关问题