Dual-Stack Sockets für IPv6 Winsock-Anwendungen

Um sowohl IPv4 als auch IPv6 unter Windows XP mit Service Pack 1 (SP1) und Windows Server 2003 zu unterstützen, muss eine Anwendung zwei Sockets erstellen, einen Socket für die Verwendung mit IPv4 und einen Socket für die Verwendung mit IPv6. Diese beiden Sockets müssen von der Anwendung separat behandelt werden.

Windows Vista und höher bieten die Möglichkeit, einen einzelnen IPv6-Socket zu erstellen, der sowohl IPv6- als auch IPv4-Datenverkehr verarbeiten kann. Beispielsweise wird ein TCP-Lauschocket für IPv6 erstellt, in den Dual Stack-Modus versetzt und an Port 5001 gebunden. Dieser Dual-Stack-Socket kann Verbindungen von IPv6-TCP-Clients akzeptieren, die eine Verbindung mit Port 5001 herstellen, und von IPv4-TCP-Clients, die eine Verbindung mit Port 5001 herstellen. Dieses Feature ermöglicht ein stark vereinfachtes Anwendungsdesign und reduziert den Ressourcenaufwand, der für die Buchung von Vorgängen in zwei separaten Sockets erforderlich ist.

Erstellen eines Dual-Stack Sockets

Standardmäßig wird ein unter Windows Vista und höher erstellter IPv6-Socket nur über das IPv6-Protokoll ausgeführt. Um einen IPv6-Socket in einen Dual-Stack-Socket zu verwandeln, muss die Setockopt-Funktion mit der Option IPV6_V6ONLY Socket aufgerufen werden, um diesen Wert auf Null festzulegen, bevor der Socket an eine IP-Adresse gebunden wird. Wenn die IPV6_V6ONLY Socketoption auf Null festgelegt ist, kann ein Socket, der für die AF_INET6 Adressfamilie erstellt wurde, verwendet werden, um Pakete an und von einer IPv6-Adresse oder einer IPv4-zugeordneten Adresse zu senden und zu empfangen.

IP-Adressen mit Dual-Stack Socket

Dual-Stack-Sockets erfordern immer IPv6-Adressen. Die Möglichkeit, mit einer IPv4-Adresse zu interagieren, erfordert die Verwendung des IPv4-zugeordneten IPv6-Adressformats. Alle IPv4-Adressen müssen im IPv4-zugeordneten IPv6-Adressformat dargestellt werden, sodass eine reine IPv6-Anwendung mit einem IPv4-Knoten kommunizieren kann. Das IPv4-adressformat ermöglicht es, die IPv4-Adresse eines IPv4-Knotens als IPv6-Adresse darzustellen. Die IPv4-Adresse ist in die 32 Bits der IPv6-Adresse mit niedriger Reihenfolge codiert, und die hohen 96 Bits enthalten das feste Präfix 0:0:0:0:0:FFFF. Das IPv4-zugeordnete IPv6-Adressformat wird in RFC 4291 angegeben. Weitere Informationen finden Sie unter www.ietf.org/rfc/rfc4291.txt. Das IN6ADDR_SETV4MAPPED Makro in "Mstcpip.h " kann verwendet werden, um eine IPv4-Adresse in das erforderliche IPv4-Adressformat zu konvertieren.

Wenn das zugrunde liegende Protokoll tatsächlich IPv4 ist, wird die IPv4-Adresse einem IPv4-zugeordneten IPv6-Adressformat zugeordnet. Dies ist das Familienfeld in der SOCKADDR-Struktur , das AF_INET6 angibt, aber eine IPv4-zugeordnete IPv6-Adresse ist in der IPv6-Adressstruktur codiert. Für einen Dual-Stack-Socket im Lauschmodus bedeutet dies, dass alle akzeptierten IPv4-Verbindungen eine IPv4-zugeordnete IPv6-Adresse zurückgeben. Für einen Dual-Stack-Socket, der eine Verbindung mit einem IPv4-Ziel herstellt, muss die SOCKADDR-Struktur, die an die Verbindung übergeben wird, eine IPv4-zugeordnete IPv6-Adresse sein. Anwendungen müssen darauf achten, diese IPv4-zugeordneten IPv6-Adressen angemessen zu behandeln und sie nur mit Dual Stack-Sockets zu verwenden. Wenn eine IP-Adresse an einen regulären IPv4-Socket übergeben werden soll, muss die Adresse eine reguläre IPv4-Adresse und keine IPv4-zugeordnete IPv6-Adresse sein.

Potenzielle Probleme bei der Verwendung eines Dual-Stack Sockets

Ein potenzieller Fallstrick für Anwendungen besteht darin, eine IPv4-zugeordnete IPv6-Adresse auf einem Dual-Stack-Socket zu erhalten und dann zu versuchen, die zurückgegebene IP-Adresse für einen anderen IPv6-Nur-Socket zu verwenden. Beispielsweise können die Funktionen getockname oder getpeername eine IPv4-zugeordnete IPv6-Adresse zurückgeben, wenn sie in einem Dual-Stack-Socket verwendet wird. Wenn die zurückgegebene IPv4-zugeordnete IPv6-Adresse anschließend für einen anderen Socket verwendet wird, der nicht auf Dual-Stack festgelegt wurde (ein IPv6-Socket, der das Standardverhalten beim Erstellen eines Sockets ist), schlägt jede Verwendung dieses IPv6-nur-Sockets mit einer IPv4-zugeordneten IPv6-Adresse fehl. Das IPv4-zugeordnete IPv6-Adressformat kann nur in einem Dual-Stack-Socket verwendet werden.

Wenn eine Anwendung in einem Dual-Stack-Datagrammsocket die funktion LPFN_WSARECVMSG (WSARecvMsg) benötigt, um Paketinformationen in einer WSAMSG-Struktur für Datagramme zurückzugeben, die über IPv4 empfangen wurden, muss IP_PKTINFO Socketoption auf true für den Socket festgelegt werden. Wenn nur die Option IPV6_PKTINFO für den Socket auf true festgelegt ist, werden Paketinformationen für Datagramme bereitgestellt, die über IPv6 empfangen wurden, aber möglicherweise nicht für Datagramme, die über IPv4 empfangen wurden.

Wenn eine Anwendung versucht, die IP_PKTINFO Socketoption für einen Dual-Stack-Datagrammsocket festzulegen und IPv4 auf dem System deaktiviert ist, schlägt die setockopt-Funktion fehl, und WSAGetLastError wird mit dem Fehler WSAEINVAL zurückgegeben. Derselbe Fehler wird auch von der funktion setsockopt als Ergebnis anderer Fehler zurückgegeben. Wenn eine Anwendung versucht, eine IPPROTO_IP-Level-Socketoption für einen Dual-Stack-Socket festzulegen, und dies mit WSAEINVAL zu einem Fehler führt, sollte die Anwendung ermitteln, ob IPv4 auf dem lokalen Computer deaktiviert ist. Eine Methode, mit der erkannt werden kann, ob IPv4 aktiviert oder deaktiviert ist, ist das Aufrufen der Socketfunktion mit dem af-Parameter , der auf AF_INET festgelegt ist, um einen IPv4-Socket zu erstellen. Wenn die Socketfunktion fehlschlägt und WSAGetLastError einen Fehler von WSAEAFNOSUPPORT zurückgibt, bedeutet dies, dass IPv4 nicht aktiviert ist. In diesem Fall kann ein Setockopt-Funktionsfehler beim Festlegen der IP_PKTINFO Socketoption von der Anwendung ignoriert werden. Andernfalls sollte ein Fehler beim Festlegen der IP_PKTINFO Socketoption als unerwarteter Fehler behandelt werden.

Bei einem Dual-Stack-Socket beim Senden von Datagrammen mit der WSASendMsg-Funktion und einer Anwendung, die eine bestimmte lokale IP-Quelladresse angeben möchte, die verwendet werden soll, hängt die Methode zum Behandeln dieser Methode von der Ziel-IP-Adresse ab. Beim Senden an eine IPv4-Zieladresse oder eine IPv4-zugeordnete IPv6-Zieladresse sollte eines der Steuerelementdatenobjekte, die in der WSAMSG-Struktur übergeben werden, auf die der lpMsg-Parameter verweist, eine in_pktinfo-Struktur enthalten, die die lokale IPv4-Quelladresse enthält, die für das Senden verwendet werden soll. Beim Senden an eine IPv6-Zieladresse, die keine IPv4-zugeordnete IPv6-Adresse ist, sollte eines der Steuerelementdatenobjekte, die in der WSAMSG-Struktur übergeben werden, auf die der lpMsg-Parameter verweist, eine in6_pktinfo-Struktur enthalten, die die lokale IPv6-Quelladresse enthält, die zum Senden verwendet werden soll.

IPv6-Leitfaden für Windows Sockets-Anwendungen

Ändern von Datenstrukturen für IPv6-Winsock-Apps

Funktionsaufrufe für IPv6-Winsockanwendungen

Verwendung von hartcodierten IPv4-Adressen

Probleme mit der Benutzeroberfläche für IPv6-Winsock-Anwendungen

Zugrunde liegende Protokolle für IPv6-Winsock-Anwendungen

getpeername

getsockname

in_pktinfo

in6_pktinfo

IP_PKTINFO

IPV6_PKTINFO

setsockopt

LPFN_WSARECVMSG (WSARecvMsg)

WSASendMsg