2012-11-22 76 views
5

我正在嘗試編寫一個監聽IPv4和IPv6地址的Web服務器。但是,我最初編寫的代碼無效。然後我發現IPv6結構既適用於IPv4也適用於IPv6。因此,現在我使用IPv6結構,但只有IPv4地址有效。這篇文章,why can't i bind ipv6 socket to a linklocal address,這表示要添加server.sin6_scope_id = 5;所以我這樣做,但它仍然不接受IPv6 telnet連接。任何幫助將不勝感激,因爲我徹底難倒了。
謝謝!將套接字綁定到IPv6地址

我的代碼如下:

void initialize_server(int port, int connections, char* address) 
{ 
     struct sockaddr_in6 socket_struct; 
     /*Creates the socket*/ 
     if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
     { 
       syslog(LOG_ERR, "%s\n", strerror(errno)); 
       exit(EXIT_FAILURE); 
     }/*Ends the socket creation*/ 

     /*Populates the socket address structure*/ 
       socket_struct.sin6_family = AF_INET6; 

     if(address == NULL) 
       socket_struct.sin6_addr=in6addr_any; 
     else 
     { 
       inet_pton(AF_INET6, "fe80::216:3eff:fec3:3c22", (void *)&socket_struct.sin6_addr.s6_addr); 
     } 
     socket_struct.sin6_port =htons(port); 
     socket_struct.sin6_scope_id = 0; 
     if (bind(sock_fd, (struct sockaddr*) &socket_struct, sizeof(socket_struct)) < 0) 
     { 
       syslog(LOG_ERR, "%s\n", strerror(errno)); 
       exit(EXIT_FAILURE); 
     }//Ends the binding. 

     if (listen(sock_fd, connections) <0) 
     { 
       syslog(LOG_ERR, "%s\n", strerror(errno)); 
       exit(EXIT_FAILURE); 
     }//Ends the listening function 

}//ends the initialize server function. 
+0

我知道ipv6是64位的,所以使用ipv6的服務器必須在64位操作系統上運行。現在只需要使用ipv4,到目前爲止使用ipv6存在很多問題。 – GiantHornet

+2

@GiantHornet:IPv6既不是32位也不是64位;它也可以在其他系統上運行。 –

+0

@GiantHornet是啊,我不認爲這是正確的,因爲我的Ubuntu機是i686這是32位,並有一個IPv6地址 – tpar44

回答

7

你在AF_INET家庭創造一個插座,但當時試圖將其綁定到一個地址在AF_INET6家庭。在撥打電話socket()時切換到使用AF_INET6

+0

感謝您的提示,但它仍然無法正常工作... – tpar44

+0

讓這個改變讓它爲我工作。 – qqx

+0

剛剛出於好奇你使用'telnet fe80 :: 216:3eff:fec3:3c22%eth0 8080'來測試它嗎? – tpar44

6

說「server.sin6_scope_id = 5;」是任意的。我和我一起打了一陣子,發現你需要使用你想綁定的實際界面的實際範圍。它可以找到一個模糊但有用的小功能。

#include <net/if.h> 
server.sin6_scope_id=if_nametoindex("eth0"); 

當然,硬編碼到一個特定的適配器是壞的,短視的編碼。一個更完整的解決方案是遍歷所有這些並匹配你綁定的IP地址。以下是不完美的,因爲它沒有考慮到像非規範地址和兩個具有相同IP地址的適配器等怪癖。但總的來說,這個示例函數很好,並且應該讓你開始。

#include <string.h> // strcmp 
#include <net/if.h> // if_nametoindex() 
#include <ifaddrs.h> // getifaddrs() 
#include <netdb.h> // NI_ constants 

// returns 0 on error 
unsigned getScopeForIp(const char *ip){ 
    struct ifaddrs *addrs; 
    char ipAddress[NI_MAXHOST]; 
    unsigned scope=0; 
    // walk over the list of all interface addresses 
    getifaddrs(&addrs); 
    for(ifaddrs *addr=addrs;addr;addr=addr->ifa_next){ 
     if (addr->ifa_addr && addr->ifa_addr->sa_family==AF_INET6){ // only interested in ipv6 ones 
      getnameinfo(addr->ifa_addr,sizeof(struct sockaddr_in6),ipAddress,sizeof(ipAddress),NULL,0,NI_NUMERICHOST); 
      // result actually contains the interface name, so strip it 
      for(int i=0;ipAddress[i];i++){ 
       if(ipAddress[i]=='%'){ 
        ipAddress[i]='\0'; 
        break; 
       } 
      } 
      // if the ip matches, convert the interface name to a scope index 
      if(strcmp(ipAddress,ip)==0){ 
       scope=if_nametoindex(addr->ifa_name); 
       break; 
      } 
     } 
    } 
    freeifaddrs(addrs); 
    return scope; 
} 
相關問題