適用於 IPv6 Winsock 應用程式的 Dual-Stack 套接字
為了在 Windows XP Service Pack 1(SP1) 和 Windows Server 2003 上同時支援 IPv4 和 IPv6 上的 IPv4 和 IPv6,應用程式必須建立兩個套接字、一個套接字與 IPv4 搭配使用,以及一個套接字來搭配 IPv6 使用。 這兩個套接字必須由應用程式分開處理。
Windows Vista 和更新版本可讓您建立單一 IPv6 套接字,以處理 IPv6 和 IPv4 流量。 例如,會建立 IPv6 的 TCP 接聽套接字、放入雙堆棧模式,並系結至埠 5001。 這個雙堆棧套接字可以接受從連線到埠 5001 的 IPv6 TCP 用戶端,以及從連線到埠 5001 的 IPv4 TCP 用戶端進行連線。 這項功能可大幅簡化應用程式設計,並減少在兩個個別套接字上張貼作業所需的資源額外負荷。
建立 Dual-Stack 套接字
根據預設,在 Windows Vista 和更新版本上建立的 IPv6 套接字只會透過 IPv6 通訊協定運作。 若要將 IPv6 套接字設為雙堆疊套接字,必須在套接字系結至 IP 位址之前,使用 IPV6_V6ONLY 套接字選項呼叫 setsockopt 函式。 當 [IPV6_V6ONLY 套接字] 選項設定為零時,針對 AF_INET6 位址系列建立的套接字可用來傳送和接收 IPv6 位址或 IPv4 對應位址的封包。
具有 Dual-Stack 套接字的IP位址
雙堆棧套接字一律需要 IPv6 位址。 與 IPv4 位址互動的能力需要使用 IPv4 對應 IPv6 位址格式。 任何 IPv4 位址都必須以 IPv4 對應 IPv6 位址格式來表示,這可讓只有 IPv6 的應用程式與 IPv4 節點通訊。 IPv4 對應 IPv6 位址格式可讓 IPv4 節點的 IPv4 位址表示為 IPv6 位址。 IPv4 位址會編碼為 IPv6 位址的低序 32 位,而高階 96 位則保留固定前置詞 0:0:0:0:0:FFFF。 IPv4 對應 IPv6 位址格式是在 RFC 4291 中指定。 如需詳細資訊,請參閱 www.ietf.org/rfc/rfc4291.txt。 Mstcpip.h 中的IN6ADDR_SETV4MAPPED巨集可用來將 IPv4 位址轉換成必要的 IPv4 對應 IPv6 位址格式。
如果基礎通訊協議實際上是IPv4,則IPv4位址會對應到IPv4對應IPv6位址格式。 也就是說,SOCKADDR 結構中的系列欄位表示AF_INET6,但 IPv4 對應的 IPv6 位址會編碼在 IPv6 位址結構中。 對於接聽模式中的雙堆疊套接字,這表示任何接受的 IPv4 連線都會傳回 IPv4 對應 IPv6 位址。 如果是連線到 IPv4 目的地的雙堆疊套接字,傳遞至連接的 SOCKADDR 結構必須是 IPv4 對應的 IPv6 位址。 應用程式必須小心處理這些 IPv4 對應 IPv6 位址,並只將它們與雙堆疊套接字搭配使用。 如果要將IP位址傳遞至一般IPv4套接字,地址必須是一般IPv4位址,而不是IPv4對應IPv6位址。
使用 Dual-Stack 套接字的潛在問題
應用程式的潛在陷阱是在雙堆疊套接字上取得 IPv4 對應的 IPv6 位址,然後嘗試在不同的 IPv6 專用套接字上使用傳回的 IP 位址。 例如,getockname 或 getpeername 函式可以在雙堆棧套接字上使用時傳回 IPv4 對應 IPv6 位址。 如果傳回的 IPv4 對應 IPv6 位址隨後用於未設定為雙重堆疊的不同套接字上(建立套接字時,只有 IPv6 的套接字是預設行為),則任何使用此 IPv6 僅具有 IPv4 對應 IPv6 位址的套接字將會失敗。 IPv4 對應的 IPv6 位址格式只能在雙堆疊套接字上使用。
在雙堆棧數據報套接字上,如果應用程式需要 LPFN_WSARECVMSG (WSARecvMsg) 函式,才能針對透過 IPv4 接收的數據報傳回封包資訊 WSAMSG 結構,則必須在套接字上將 IP_PKTINFO 套接字選項設定為 true。 如果套接字上只有 IPV6_PKTINFO 選項設定為 true,則會針對透過 IPv6 接收的數據報提供封包資訊,但可能無法針對透過 IPv4 接收的數據報提供。
如果應用程式嘗試在雙堆疊數據報套接字上設定 IP_PKTINFO 套接字選項,且系統上已停用 IPv4,則 setockopt 函式將會失敗,且 WSAGetLastError 會傳回,且 WSAEINVAL錯誤。 由於其他錯誤,setsockopt 函式也會傳回這個相同的錯誤。 如果應用程式嘗試在雙堆疊套接字上設定IPPROTO_IP層級套接字選項,而且它因 WSAEINVAL而失敗,則應用程式應該判斷本機計算機上是否停用 IPv4。 其中一個可用來偵測 IPv4 已啟用或停用的方法,就是呼叫 套接字 函式,並將 af 參數設定為 AF_INET,以嘗試建立 IPv4 套接字。 如果 套接字 函式失敗,且 WSAGetLastError 傳回 WSAEAFNOSUPPORT的錯誤,則表示未啟用 IPv4。 在此情況下,應用程式可以忽略嘗試設定 IP_PKTINFO 套接字選項時,setsockopt 函式失敗。 否則,嘗試設定 IP_PKTINFO 套接字選項時發生失敗,應視為非預期的錯誤。
針對使用 WSASendMsg 傳送數據報時,雙堆疊套接字 函式,而應用程式想要指定要使用的特定本機 IP 來源地址,處理此方法取決於目的地 IP 位址。 傳送至 IPv4 目的地位址或 IPv4 對應 IPv6 目的地位址時,傳入 WSAMSG 結構中傳遞的其中一個控制數據物件,lpMsg 參數所指向的其中一個控制數據對象應該包含 in_pktinfo 結構,其中包含要用於傳送的本機 IPv4 來源位址。 當傳送至不是 IPv4 對應 IPv6 位址的 IPv6 目的地位址時,傳入 WSAMSG 結構中傳遞的其中一個控制數據物件,lpMsg 參數所指向的其中一個控制數據對象應該包含 in6_pktinfo 結構,其中包含要用於傳送的本機 IPv6 來源位址。
相關主題