2012-11-08 86 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

相關問題