2015-06-22 38 views
0

我試圖將我的本地IPv6地址綁定到套接字。但總是得到「無效論證」。我想將特定IP地址綁定到套接字的原因是,如果我不綁定錯誤「無路由到主機」出現。當我嘗試用下面的命令ping一個IPv6地址時,它不起作用。套接字編程:bind() - 無效的參數

ping6 fe80::7ed1:c3ff:fe86 

我必須指出我想從哪個接口發送數據包。

ping6 -I en1 fe80::7ed1:c3ff:fe86 

這工作正常。所以我認爲如果我將套接字綁定到接口上,那麼我可以成功發送數據包。 任何人都可以告訴我如何發送IPv6地址而無需指定接口或如何解決這個綁定問題?

這裏是代碼。

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <netdb.h> 

#define LOCALADDR "fe80::7ed1:c3ff:fe86:ddae" 

int main(void) 
{ 
int sock,status; 
struct addrinfo local_addr; 
struct addrinfo *servinfo; 
char buffer[1024]; 

/* create a DGRAM (UDP) socket in the INET6 (IPv6) protocol */ 
sock = socket(PF_INET6, SOCK_DGRAM, 0); 

if (sock < 0) { 
    perror("creating socket"); 
    exit(1); 
} 

/*Binding specific interface to socket*/ 
memset(&local_addr, 0, sizeof(local_addr)); 
local_addr.ai_family = AF_INET6; 
local_addr.ai_socktype = SOCK_DGRAM; 
local_addr.ai_flags = AI_PASSIVE; 

if ((status = getaddrinfo(NULL, "3535", &local_addr, &servinfo)) != 0) { 
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status)); 
    exit(1); 
} 

if (bind(sock, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0) 
    error("ERROR on binding"); 

我也試圖在 「的getaddrinfo」 來代替 「NULL」 是 「LOCALADDR」。

if ((status = getaddrinfo(LOCALADDR, "3535", &local_addr, &servinfo)) != 0) { 
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status)); 
    exit(1); 
} 

而且我仍然遇到同樣的問題。

我可以用「in6addr_any」成功綁定套接字,但後來出現錯誤「No route to host」。

回答

0

這是一個鏈路本地IPv6地址,而不是可路由的IPv6地址。鏈路本地地址專用於鏈路,並且每個鏈路可以具有與其他鏈路相同的地址。例如,如果您有三個不同的接口,則可以爲每個接口分配相同的鏈路本地地址。要使用鏈接本地地址,您需要指定接口,以便操作系統知道使用哪個鏈接。所有接口將在同一網絡中具有鏈路本地地址:fe80 ::/10。

如果使用可路由的IPv6地址,則不需要指定接口。

0

您正在錯誤地創建套接字。 '域'(第一個參數)應該是AF_INET6,而不是PF_INET6。我不確定這些宏是否在您的環境中擴展到了不同的值,但是爲此目的指定的宏是AF_*

否則,對於接受連接的套接字,您應該獲得一個地址,這與您首次出現的方式非常相似。特別地,對於getaddrinfo()文檔說

如果AI_PASSIVE標誌在hints.ai_flags指定,並且node是NULL,則返回的套接字地址將適合於bind(2)壞的插座即會accept(2)連接。返回的套接字地址將包含「通配符地址」(IPv4地址爲INADDR_ANY,IPv6地址爲IN6ADDR_ANY_INIT)。應用程序(通常是服務器)使用通配符地址,以便接受任何主機的網絡地址上的連接。如果node不爲NULL,則忽略AI_PASSIVE標誌。

因此,你當然可以或許應該指定一個NULL第一個參數。

但是,請注意,getaddrinfo()會返回地址的鏈接列表,並且在某些情況下,需要選擇與第一個不同的地址。不過,我認爲首先應該在這種特殊情況下罰款。

請注意,嘗試連接的客戶端的「無路由到主機」消息並不一定表示服務器未在偵聽。很可能是客戶使用錯誤的地址(c.f. @ RonMaupin的回答),或者正如它所說的那樣,從客戶端到服務器之間沒有(已知的)通過網絡的路由。例如,這可能是由於路由器或防火牆配置引起的。

+0

「'域'(第一個參數)應該是AF_INET6,而不是PF_INET6」 這在每個平臺上都不是這樣;在OS X「man」狀態下,你應該使用PF _ * - 。 –

+1

@ K.Biermann,蘋果自己的在線手冊頁([1](https://developer.apple.com/library/ios/documentation/System/Conceptual/ManPages_iPhoneOS/man2/socket.2.html),[2] (https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/socket.2.html))不同,但[POSIX docs](http://pubs.opengroup。 org/onlinepubs/009695399/functions/socket.html)引用了符號的sys/socket.h,並且該頭文件需要提供AF_INET6和朋友,但沒有提及PF_ *符號在所有。 –

+1

@ K.Biermann,如果你想編寫* portable *代碼,所以你使用'AF_ *'常量。如果您的平臺使用與相應的標準AF_ *常量不同的值定義了'PF_ *'常量,或者它根本不提供'AF_ *'常量,那麼是時候考慮找到一個不需要的工作開發這樣一個不正常的環境。但我不認爲OS X屬於這一類。 –