我正在試驗IPv6套接字,尤其是在Windows Vista和更高版本上提供的「雙棧」功能,顯然在Unix上默認情況下。我發現當我將服務器綁定到特定的IP地址或本地計算機的主機名解析時,我無法接受來自IPv4客戶端的連接。當我綁定到INADDR_ANY但是,我可以。將IPv4客戶端連接到IPv6服務器:連接被拒絕
請爲我的服務器考慮下面的代碼。你可以看到,我按照創建一個IPv6套接字,那麼IPV6_V6ONLY標誌設置爲零的微軟的建議是:
addrinfo* result, *pCurrent, hints;
memset(&hints, 0, sizeof hints); // Must do this!
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // We intend to use the addrinfo in a call to connect(). (I know it is ignored if we specify a server to connect to...)
int nRet = getaddrinfo("powerhouse", "82", &hints, &result);
SOCKET sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
int no = 0;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no)) != 0)
return -1;
if (bind(sock, result->ai_addr, result->ai_addrlen) == SOCKET_ERROR)
return -1;
if (listen(sock, SOMAXCONN) == SOCKET_ERROR)
return -1;
SOCKET sockClient = accept(sock, NULL, NULL);
這裏是我的客戶端代碼。你可以看到我創建IPv4套接字,並嘗試連接到我的服務器:從我的連接調用
addrinfo* result, *pCurrent, hints;
memset(&hints, 0, sizeof hints); // Must do this!
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo("powerhouse", "82", &hints, &result) != 0)
return -1;
SOCKET sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
int nRet = connect(sock, result->ai_addr, result->ai_addrlen);
結果總是10061:連接被拒絕。
如果我將服務器代碼更改爲綁定到::(或將NULL主機傳遞給getaddrinfo()(同樣的事情)),並更改我的客戶端代碼以在getaddrinfo()調用中指定NULL主機,則V4客戶端可以很好地連接。
任何人都可以解釋爲什麼請嗎?如果我們需要雙套接字行爲,我沒有讀過任何必須指定NULL主機的東西(因此使用INADDR_ANY)。這不是一個要求,因爲我有一個多宿主主機,並且我只想在某些可用的IP上接受IPv4?
編輯15/05/2013:
這是有關文件已經得到了我的困惑,爲什麼我的代碼失敗:
從Dual-Stack Sockets for IPv6 Winsock Applications
「Windows Vista和後來提供了創建一個可以同時處理IPv6和IPv4流量的單個IPv6套接字的功能,例如,創建一個用於IPv6的TCP偵聽套接字,將其插入雙協議棧K色模式,和 綁定到端口5001。這種雙棧插座可以接受來自 IPv6的TCP客戶端的連接連接到端口5001,並從連接到端口5001。「
」的IPv4 TCP客戶 缺省情況下,IPv6套接字在Windows Vista上創建,後來只有 在IPv6協議上運行。爲了在 中創建一個雙棧套接字的IPv6套接字,必須使用IPV6_V6ONLY套接字選項調用setsockopt函數,以便在將套接字 綁定到IP地址之前將此值設置爲零。 當IPV6_V6ONLY套接字選項設置爲 爲零時,可以使用爲AF_INET6地址系列創建的套接字 來發送和接收來自IPv6地址或IPv4地址的數據包和從IPv4地址或IPv4 映射的地址發送和接收數據包。(重點煤礦)」
您需要一個用於IPv4連接的IPv4端點,「綁定」顯式是IPv6端點而不是通配符。 – 2013-05-10 12:51:08
@史蒂夫o我不明白你的意思,對不起。你能澄清嗎? – Wad 2013-05-10 12:57:52
綁定實現了一個過濾器,只接受與綁定地址匹配的目標地址的數據。 IPv4數據包將具有IPv4目標地址,因此將被拒絕。 – 2013-05-10 17:43:44