2014-12-04 121 views
6

我有一個服務器實現,我需要2個獨立的套接字 - 一個偵聽特定IPv4地址和服務器端口X的IPv4套接字套接字,以及一個偵聽特定IPv6地址和同一個服務器端口X的IPv6套接字。 IPv4和IPv6地址位於相同的接口上。IPv6綁定失敗

memset(&sin, 0, sizeof(sin)); 
    sin.sin_family  = AF_INET; 
    sin.sin_addr.s_addr = htonl(v4addr); 
    sin.sin_port  = htons(tcp_port); 

我使用evconnlistener_new_bind創建IPv4套接字,並綁定到它。 對於IPv6偵聽器,代碼如下。

memset(&sin6, 0, sizeof(sin6)); 
    sin6.sin6_family  = AF_INET6; 
    memcpy(sin6.sin6_addr.s6_addr, v6addr_bytes, IPV6_ADDR_LEN); 
    sin6.sin6_port  = htons(tcp_port); 

    fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 
    evutil_make_socket_nonblocking(fd) 
    setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on)) 
    setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&on, sizeof(on)) 
    evutil_make_listen_socket_reuseable(fd) /* Libevent call to set SO_REUSEADDR */ 
    evutil_make_socket_nonblocking(fd)  /* Libevent call to set fd non-blocking */ 
    bind(fd, (const struct sockaddr *)&sin6, sizeof(sin6)) 

正如我在我的FD綁定到特定的IPv6地址,我看到一個綁定失敗間歇。

綁定V6失敗sin6 3FFE :: A00:513 - 錯誤號99 - 無法分配請求的地址

我試圖在gdb的,但我每次在gdb的時候,綁定成功。

我不知道爲什麼我看到這個問題。有人可以幫忙嗎?

+0

Addreses在'3FFE ::/16'無效。改爲使用有效的IPv6地址。 – 2014-12-04 19:01:51

+0

我的界面有一個3ffe :: 10.1.14.14/120地址。在創建套接字時,前綴掩碼沒有影響嗎?你爲什麼說它是一個無效的地址? – shrejal 2014-12-05 20:49:30

+0

因爲它無效。那個網塊在幾年前就已經過時了。而且它完全被使用的事實表明,你的IPv6設置有些可怕的錯誤。首先解決它。 – 2014-12-05 20:52:04

回答

0

默認情況下,在將套接字綁定到TCP端口後,當套接字關閉時端口保留一分鐘 - 這稱爲TCP TIME_WAIT狀態。 TIME_WAIT可以避免一些可能導致數據損壞的競爭條件,但通常在服務器端忽略TIME_WAIT是安全的。

這是通過設置SO_REUSEADDR套接字選項來完成:

int one = 1; 
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) 
+1

要清除,當擁有的應用程序在已建立連接時主動關閉套接字(如果遠程對等方啓動關閉,套接字不會進入TIME_WAIT),套接字將進入TIME_WAIT狀態。然後,您可以在要綁定到先前綁定的ip +端口的NEXT套接字上啓用'SO_REUSEADDR'。 – 2014-12-19 02:37:08