2012-07-30 107 views
5

我有一個UDP服務器必須在IPV4和IPV6地址上爲客戶端服務。我創建了一個IPV6套接字來爲IPV4和IPV6客戶端提供服務。

服務器在第一次通信時存儲客戶端的IP地址。如果它是IPV4客戶端,則它存儲爲IPV4地址,如果它是IPV6客戶端,則服務器將存儲爲IPV6地址。對於將來的所有通信,它會檢查存儲器是否已知(存儲)該客戶端,然後進行相應的處理。爲了比較客戶端地址和存儲地址,我根據家庭類型(AF_INET和AF_INET6)執行了一個memcmp。

與IPV6客戶端通信時,系統正常工作,但在與IPV4客戶端通信時,系統表現得好像從來不知道客戶端一樣。在調試過程中,我發現由於IPV6是Socket Type,因此IPV4客戶端的IP地址被作爲IPV6映射的IPV4地址接收,而IPV4地址族被設置爲IPV6。爲了解決這個問題,我需要比較IPV4存儲地址和IPV6映射地址。爲此,我使用IPV4結構的sin_addr.s_addr和IPV6結構的sin6_addr.in6_u.u6_addr32。請找到下面的代碼片段。比較IPV4套接字(sockaddr_in)與IPV6套接字(sockaddr_in6)

ipv6_clientdata = (const struct sockaddr_in6 *)&sockStor; 
ipv4_storeddata = (const struct sockaddr_in *)&(_stData[index].clientaddr); 
if((ipv6_clientdata->sin6_port == ipv4_storeddata->sin_port) && 
    (ipv6_clientdata->sin6_addr.in6_u.u6_addr32[3] == ipv4_storeddata->sin_addr.s_addr) 
) 
{ 
    addrfound = true; 
} 

我想知道這種方法是否是與IPV4地址比較IPV6映射IPv4地址的妥善解決或有任何其他更好的辦法。

+0

我承認我沒有太多的IPv6經驗,但不會例如即使它是IPv6映射的IPv4地址,recvfrom也返回源地址作爲AF_INET6? – 2012-07-30 09:11:36

+0

對不起,我跳過/忘記提及以下功能。服務器通過兩種方式獲取客戶端地址。 1)第一次與客戶端通過UDP進行通信2)客戶端可能通過TCP將其UDP連接細節作爲XML數據發佈到服務器。在這種情況下,客戶將只提供IPV4地址。 – 2012-07-30 09:13:42

+3

在比較最後的32位之前,還需要檢查前80位是否爲零,接下來的16位是否爲1。否則,您不知道您是否正在處理映射爲IPV6的IPV4。 – 2012-07-30 10:08:17

回答

2

由於Joachim Pileborg的推理,當IPv4地址來自同一個套接字上收到的較早數據包時,您不需要關心這一點,因爲您將比較一個映射的IPv4地址與另一個。只有在IPv4地址從外部來源獲得的情況下,您必須注意。

由於João Augusto指出,您忽略了在比較最後32位之前檢查IPv6地址的確是IPv4映射地址。有一個宏IN6_IS_ADDR_V4MAPPED,這將幫助你這樣做:

if (
    IN6_IS_ADDR_V4MAPPED(&(ipv6_clientdata->sin6_addr)) && 
    (ipv6_clientdata->sin6_port == ipv4_storeddata->sin_port) && 
    (ipv6_clientdata->sin6_addr.in6_u.u6_addr32[3] == ipv4_storeddata->sin_addr.s_addr) 
) { 
    addrfound = true; 
}