2012-11-22 124 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; 
} 
相关问题