1. 程式人生 > >讓你的Socket應用相容IPv6

讓你的Socket應用相容IPv6

 隨著網際網路越來越普及,以及物聯網的興起,IPv4地址已遠遠不夠用,IPv6的普及將是不可避免的趨勢。以前,我們的大部分socket程式幾乎都是針對IPv4而開發,如果不做升級重構,那麼使用IPv6地址的客戶端將無法使用服務端提供的服務。如何才能像ESFramework一樣,使服務端和客戶端都可以同時支援IPv6了?使我們的P2P打洞也相容IPv6了?下面我們將要點一一點出。

      首先,要了解兩個最基礎的事實:

(1)通訊的雙方,無論是服務端與客戶端之間,或是客戶端與客戶端之間的P2P通訊,必須使用相同的協議版本 -- 要麼都是IPv4,要麼都是IPv6。

(2)在沒有特別安裝附件的情況下,有的OS可能只支援IPv4,有的可能只支援IPv6,有的即支援IPv4也支援IPv6。可以通過Socket

類的OSSupportsIPv6和OSSupportsIPv4屬性來作判斷。

一.TCP服務端

      要讓TCP服務端即能夠接收IPv4地址的客戶端的請求,也能接收IPv6地址客戶端的請求,前提是伺服器的OS即支援IPv4也支援IPv6。預設的,windows 2003 Server 是隻支援IPv4的,可以通過安裝協議來使其支援IPv6。

      然後,寫服務端程式時,必需同時監聽本機IPv4地址和IPv6地址,並且是監聽這兩個地址的同一個埠。比如,像下面這樣:

 int port = 9900;
 TcpListener tcpListenerV4 = new TcpListener
(IPAddress.Any, port); TcpListener tcpListenerV6
= new TcpListener(IPAddress.IPv6Any, port);

      如此,客戶端無論是使用的IPv4還是IPv6,其向服務端發起連線請求時,都可以被服務端接受。

二.TCP客戶端

      我們現在假設服務端程式已經相容了IPv6,並且其提供服務的IPv4地址為192.168.0.104,IPv6地址為fe80::14d8:a209:89e6:c162%14。

      那麼TCP客戶端在與服務端建立連線之前,要看本地OS對IPv4和IPv6的支援情況:

(1)如果本地OS僅支援IPv4,或者同時支援IPv4和IPv6,那麼簡單地,就讓其連線到伺服器的IPv4地址。示例程式碼如下所示:

 TcpClient client = new TcpClient(AddressFamily.InterNetwork);
 client.Connect("192.168.0.104", 9900);

(2)如果本地OS僅支援IPv6,那麼,就讓其連線到伺服器的IPv6地址。示例程式碼如下所示:

 TcpClient client = new TcpClient(AddressFamily.InterNetworkV6);
 client.Connect("fe80::14d8:a209:89e6:c162%14", 9900); 

三.UDP

      對於UDP而言,服務端和客戶端可以採用完全一樣的模型。要讓基於UDP的應用程式相容IPv6,會稍微複雜一些。

(1)需要建立兩個UdpClient例項,一個用於IPv4,一個用於IPv6。示例程式碼如下所示:

 int port = 9800;
 UdpClient udpClient4 = new UdpClient(port, AddressFamily.InterNetwork);
 UdpClient udpClient6 = new UdpClient(port ,AddressFamily.InterNetworkV6);

(2)需要在兩個UdpClient例項上呼叫接收資料的方法,來接收資料。
(3)傳送資料時,需要根據目標地址是IPv4還是IPv6,來選擇正確的UdpClient例項進行傳送。示例程式碼如下所示:

    public void Send(byte[] data, IPEndPoint endPoint)
    {
        if (endPoint.AddressFamily == AddressFamily.InterNetwork)
        {
            this.udpClient4.Send(data, data.Length, endPoint);
        }
        else
        {
            this.udpClient6.Send(data, data.Length, endPoint);
        }
    }
      上面的示例,我們是假設當前的OS同時支援IPv4和IPv6,如果僅僅支援其中的一個,那麼就應該只建立udpClient4或udpClient6一個例項。

四.P2P與IPv6

      如果我們的TCP客戶端以及UDP都按照了上面類似的方式進行了重構升級,那麼,無論是基於TCP的P2P打洞,還是基於UDP的P2P打洞,其邏輯程式碼都不需要做任何修改,就可以完全相容IPv6了。

      本文只是列出了將Socket應用程式重構升級使其支援IPv6的要點,在實際實現的過程中,還有很多的細節需要處理,才能在現實的複雜環境中正常執行。這裡就不再贅述了,有疑問的朋友可以留言討論。謝謝。