Funktionsaufrufe für IPv6-Winsock-Anwendungen

Es wurden speziell für die Windows Sockets-Schnittstelle neue Funktionen eingeführt, die die Programmierung von Windows Sockets vereinfacht. Einer der Vorteile dieser neuen Windows Sockets-Funktionen ist die integrierte Unterstützung für IPv6 und IPv4.

Diese neuen Windows Sockets-Funktionen umfassen Folgendes:

Darüber hinaus wurden neue IP-Hilfsfunktionen mit Unterstützung für IPv6 und IPv4 hinzugefügt, um die Programmierung von Windows Sockets zu vereinfachen. Diese neuen Windows Sockets-Hilfsfunktionen sind unter anderem:

Wenn Sie einer Anwendung IPv6-Unterstützung hinzufügen, sollten Sie sich an die folgenden Richtlinien halten:

  • Verwenden Sie WSAConnectByName, um eine Verbindung mit einem Endpunkt herzustellen, der einen Hostnamen und einen Port hat. Die Funktion WSAConnectByName ist unter Windows Vista und höher verfügbar.
  • Verwenden Sie WSAConnectByList, um eine Verbindung zu einem aus einer Sammlung möglicher Endpunkte herzustellen, die durch eine Reihe von Zieladressen (Hostnamen und Ports) repräsentiert werden. Die Funktion WSAConnectByList ist unter Windows Vista und höher verfügbar.
  • Ersetzen Sie Aufrufe der Funktion gethostbyname durch Aufrufe einer der neuen Windows Sockets getaddrinfo-Funktionen. Die Funktion getaddrinfo mit Unterstützung für das IPv6-Protokoll ist unter Windows XP und höher verfügbar. Das IPv6-Protokoll wird auch unter Windows 2000 unterstützt, wenn die IPv6 Technology Preview für Windows 2000 installiert ist.
  • Ersetzen Sie Aufrufe der Funktion gethostbyaddr durch Aufrufe einer der neuen Windows Sockets getnameinfo-Funktionen. Die Funktion getnameinfo mit Unterstützung für das IPv6-Protokoll ist unter Windows XP und höher verfügbar. Das IPv6-Protokoll wird auch unter Windows 2000 unterstützt, wenn die IPv6 Technology Preview für Windows 2000 installiert ist.

WSAConnectByName

Die Funktion WSAConnectByName vereinfacht die Verbindung mit einem Endpunkt mithilfe eines streambasierten Sockets mit dem Hostnamen oder der IP-Adresse des Ziels (IPv4 oder IPv6). Diese Funktion reduziert den für die Erstellung einer IP-Anwendung erforderlichen Quellcode, der unabhängig von der Version des verwendeten IP-Protokolls ist. WSAConnectByName ersetzt die folgenden Schritte in einer typischen TCP-Anwendung durch einen einzigen Funktionsaufruf:

  • Auflösen eines Hostnamens in eine Reihe von IP-Adressen.
  • Für jede IP-Adresse:
    • Erstellen eines Socket der entsprechenden Adressfamilie.
    • Versucht, eine Verbindung mit der Remote-IP-Adresse herzustellen. Wenn erfolgreich eine Verbindung hergestellt werden konnte, wird sie zurückgegeben; andernfalls wird versucht, eine Verbindung mit der nächsten Remote-IP-Adresse für den Host herzustellen.

Die Funktion WSAConnectByName geht über das Auflösen des Namens und den Versuch eine Verbindung herzustellen hinaus. Die Funktion verwendet alle von der Namensauflösung zurückgegebenen Remote-IP-Adressen und alle Quell-IP-Adressen des lokalen Computers. Sie versucht zunächst, eine Verbindung über die Adresspaaren mit der höchsten Erfolgswahrscheinlichkeit herzustellen. Daher stellt WSAConnectByName nicht nur sicher, dass nach Möglichkeit eine Verbindung hergestellt wird, sie minimiert außerdem auch die Zeit bis zum Herstellen der Verbindung.

Verwenden Sie die folgende Methode, um die IPv6- und IPv4-Kommunikation zu aktivieren:

  • Die Funktion setockopt muss für einen Socket aufgerufen werden, der für die AF_INET6 Adressfamilie erstellt wurde, um die Socketoption IPV6_V6ONLY vor dem Aufrufen von WSAConnectByName zu deaktivieren. Dazu rufen Sie die Funktion setsockopt auf dem Socket auf, wobei der Parameter level auf IPPROTO_IPV6 gesetzt ist (siehe IPPROTO_IPV6 Socket-Optionen), der Parameter optname auf IPV6_V6ONLY und der Parameter optvalue auf Null.

Wenn eine Anwendung an eine bestimmte lokale Adresse oder einen Port gebunden werden muss, kann WSAConnectByName nicht verwendet werden, da der Socket-Parameter von WSAConnectByName ein ungebundener Socket sein muss.

Das folgende Codebeispiel zeigt, dass nur wenige Zeilen Code erforderlich sind, um diese Funktion zur Implementierung einer Anwendung zu verwenden, die unabhängig von der IP-Version ist.

Herstellen einer Verbindung mit WSAConnectByName

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

SOCKET OpenAndConnect(LPWSTR NodeName, LPWSTR PortName) 
{
    SOCKET ConnSocket;
    DWORD ipv6only = 0;
    int iResult;
    BOOL bSuccess;
    SOCKADDR_STORAGE LocalAddr = {0};
    SOCKADDR_STORAGE RemoteAddr = {0};
    DWORD dwLocalAddr = sizeof(LocalAddr);
    DWORD dwRemoteAddr = sizeof(RemoteAddr);
  
    ConnSocket = socket(AF_INET6, SOCK_STREAM, 0);
    if (ConnSocket == INVALID_SOCKET){
        return INVALID_SOCKET;
    }

    iResult = setsockopt(ConnSocket, IPPROTO_IPV6,
        IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
    if (iResult == SOCKET_ERROR){
        closesocket(ConnSocket);
        return INVALID_SOCKET;       
    }

    bSuccess = WSAConnectByName(ConnSocket, NodeName, 
            PortName, &dwLocalAddr,
            (SOCKADDR*)&LocalAddr,
            &dwRemoteAddr,
            (SOCKADDR*)&RemoteAddr,
            NULL,
            NULL);
    if (bSuccess){
        return ConnSocket;
    } else {
        return INVALID_SOCKET;
    }
}

WSAConnectByList

Die Funktion WSAConnectByList stellt eine Verbindung mit einem Host her, der sich in einem Set möglicher Hosts befindet (dargestellt durch eine Reihe von Ziel-IP-Adressen und Ports). Die Funktion verwendet alle IP-Adressen und Ports für den Endpunkt und alle IP-Adressen des lokalen Rechners und versucht eine Verbindung über alle möglichen Adresskombinationen herzustellen.

WSAConnectByList ist mit der Funktion WSAConnectByName verwandt. Anstatt einen einzelnen Hostnamen zu verwenden, akzeptiert WSAConnectByList eine Liste von Hosts (Zieladressen und Port-Paare) und stellt eine Verbindung mit einer der Adressen und Ports in der bereitgestellten Liste her. Diese Funktion wurde entwickelt, um Szenarien zu unterstützen, in denen eine Anwendung eine Verbindung mit einem beliebigen verfügbaren Host aus einer Liste potenzieller Hosts herstellen muss.

Ähnlich wie die Funktion WSAConnectByName reduziert die Funktion WSAConnectByList erheblich den Quellcode, der zum Erstellen, Binden und Verbinden eines Sockets erforderlich ist. Diese Funktion erleichtert die Implementierung einer Anwendung, die unabhängig von der IP-Version ist. Die Liste der Adressen für Hosts, die von dieser Funktion akzeptiert werden, kann IPv6- oder IPv4-Adressen umfassen.

Damit sowohl IPv6- als auch IPv4-Adressen in der einzigen von der Funktion akzeptierten Adressliste übergeben werden können, müssen die folgenden Schritte vor dem Aufruf der Funktion durchgeführt werden:

  • Die Funktion setockopt muss für einen Socket aufgerufen werden, der für die AF_INET6-Adressfamilie erstellt wurde, um die Socketoption IPV6_V6ONLY vor dem Aufrufen von WSAConnectByList zu deaktivieren. Dazu rufen Sie die Funktion setsockopt auf dem Socket auf, wobei der Parameter level auf IPPROTO_IPV6 gesetzt ist (siehe IPPROTO_IPV6 Socket-Optionen), der Parameter optname auf IPV6_V6ONLY und der Parameter optvalue auf Null.
  • Alle IPv4-Adressen müssen im IPv4-zugeordneten IPv6-Adressformat dargestellt werden, damit eine reine IPv6-Anwendung mit einem IPv4-Knoten kommunizieren kann. Das IPv4-zugeordnete IPv6-Adressformat ermöglicht die Darstellung der IPv4-Adresse eines IPv4-Knotens als IPv6-Adresse. Die IPv4-Adresse wird in den niederwertigen 32 Bits der IPv6-Adresse kodiert, und die höherwertigen 96 Bits enthalten das feste Präfix 0: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 Makro IN6ADDR_SETV4MAPPED in Mstcpip.h kann verwendet werden, um eine IPv4-Adresse in das erforderliche IPv4-zugeordnete IPv6-Adressformat zu konvertieren.

Herstellen einer Verbindung mithilfe von WSAConnectByList

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

SOCKET OpenAndConnect(SOCKET_ADDRESS_LIST *AddressList) 
{
    SOCKET ConnSocket;
    DWORD ipv6only = 0;
    int iResult;
    BOOL bSuccess;
    SOCKADDR_STORAGE LocalAddr = {0};
    SOCKADDR_STORAGE RemoteAddr = {0};
    DWORD dwLocalAddr = sizeof(LocalAddr);
    DWORD dwRemoteAddr = sizeof(RemoteAddr);

    ConnSocket = socket(AF_INET6, SOCK_STREAM, 0);
    if (ConnSocket == INVALID_SOCKET){
        return INVALID_SOCKET;
    }

    iResult = setsockopt(ConnSocket, IPPROTO_IPV6,
        IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
    if (iResult == SOCKET_ERROR){
        closesocket(ConnSocket);
        return INVALID_SOCKET;       
    }

    // AddressList may contain IPv6 and/or IPv4Mapped addresses
    bSuccess = WSAConnectByList(ConnSocket,
            AddressList,
            &dwLocalAddr,
            (SOCKADDR*)&LocalAddr,
            &dwRemoteAddr,
            (SOCKADDR*)&RemoteAddr,
            NULL,
            NULL);
    if (bSuccess){
        return ConnSocket;
    } else {
        return INVALID_SOCKET;
    }
}

getaddrinfo

Die Funktion getaddrinfo führt zusätzlich die Verarbeitungsaufgaben vieler Funktionen aus. Zuvor waren Aufrufe einer Reihe von Windows Sockets-Funktionen erforderlich, um eine Adresse zu erstellen, zu öffnen und dann an einen Socket zu binden. Mit der Funktion getaddrinfo lassen sich die Zeilen des Quellcodes, die für diese Aufgabe erforderlich sind, erheblich reduzieren. Die folgenden zwei Beispiele veranschaulichen den Quellcode, der zur Durchführung dieser Aufgaben mit und ohne die Funktion getaddrinfo erforderlich ist.

Ausführen der Aufgaben „Öffnen“, „Verbindung herstellen“ und „Binden“ mithilfe von getaddrinfo

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

SOCKET OpenAndConnect(char *ServerName, char *PortName, int SocketType)
{
    SOCKET ConnSocket;
    ADDRINFO *AI;

    if (getaddrinfo(ServerName, PortName, NULL, &AI) != 0) {
        return INVALID_SOCKET;
    }

    ConnSocket = socket(AI->ai_family, SocketType, 0);
    if (ConnSocket == INVALID_SOCKET) {
        freeaddrinfo(AI);
        return INVALID_SOCKET;
    }

    if (connect(ConnSocket, AI->ai_addr, (int) AI->ai_addrlen) == SOCKET_ERROR) {
        closesocket(ConnSocket);
        freeaddrinfo(AI);
        return INVALID_SOCKET;
    }

    return ConnSocket;
}

Ausführen der Aufgaben „Öffnen“, „Verbindung herstellen“ und „Binden“ ohne getaddrinfo

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

SOCKET OpenAndConnect(char *ServerName, unsigned short Port, int SocketType) 
{
    SOCKET ConnSocket;
    LPHOSTENT hp;
    SOCKADDR_IN ServerAddr;
    
    ConnSocket = socket(AF_INET, SocketType, 0); /* Open a socket */
    if (ConnSocket < 0 ) {
        return INVALID_SOCKET;
    }

    memset(&ServerAddr, 0, sizeof(ServerAddr));
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons(Port);

    if (isalpha(ServerName[0])) {   /* server address is a name */
        hp = gethostbyname(ServerName);
        if (hp == NULL) {
            return INVALID_SOCKET;
        }
        ServerAddr.sin_addr.s_addr = (ULONG) hp->h_addr;
    } else { /* Convert nnn.nnn address to a usable one */
        ServerAddr.sin_addr.s_addr = inet_addr(ServerName);
    } 

    if (connect(ConnSocket, (LPSOCKADDR)&ServerAddr, 
        sizeof(ServerAddr)) == SOCKET_ERROR)
    {
        closesocket(ConnSocket);
        return INVALID_SOCKET;
    }

    return ConnSocket;
}

Beachten Sie, dass diese beiden Quellcodebeispiele die gleichen Aufgaben erfüllen. Das erste Beispiel, das die Funktion getaddrinfo verwendet, erfordert jedoch weniger Zeilen Quellcode und kann sowohl IPv6- als auch IPv4-Adressen verarbeiten. Die Anzahl der Zeilen des Quellcodes, die durch die Verwendung der Funktion getaddrinfo eliminiert werden, variiert.

Hinweis

Im produktiven Quellcode würde Ihre Anwendung die von der Funktion gethostbyname oder getaddrinfo zurückgegebenen Adressen durchgehen. In diesen Beispielen wird dieser Schritt zugunsten der Einfachheit weggelassen.

 

Ein weiteres Problem, mit dem Sie sich auseinandersetzen müssen, wenn Sie eine bestehende IPv4-Anwendung für die Unterstützung von IPv6 modifizieren, hängt mit der Reihenfolge zusammen, in der die Funktionen aufgerufen werden. Sowohl getaddrinfo als auch gethostbyname erfordern, dass eine Abfolge von Funktionsaufrufen in einer bestimmten Reihenfolge ausgeführt wird.

Auf Plattformen, auf denen sowohl IPv4 als auch IPv6 verwendet werden, ist die Adressfamilie des Namens des Remotehosts nicht im Voraus bekannt. Daher muss zuerst die Adressauflösung mit der Funktion getaddrinfo ausgeführt werden, um die IP-Adresse und die Adressfamilie des Remotehosts zu ermitteln. Anschließend kann die Funktion socket aufgerufen werden, um einen Socket der von getaddrinfo zurückgegebenen Adressfamilie zu öffnen. Dies ist eine wichtige Änderung in der Art und Weise, wie Windows Sockets-Anwendungen geschrieben werden, da viele IPv4-Anwendungen in der Regel eine andere Reihenfolge der Funktionsaufrufe verwenden.

Die meisten IPv4-Anwendungen erstellen zunächst einen Socket für die AF_INET-Adressfamilie, führen dann die Namensauflösung durch und verwenden dann den Socket, um sich mit der aufgelösten IP-Adresse zu verbinden. Wenn Sie solche Anwendungen IPv6-fähig machen, muss der Aufruf der Funktion socket auf einen Zeitpunkt nach der Namensauflösung verschoben werden, wenn die Adressfamilie bestimmt wurde. Wenn bei der Namensauflösung sowohl IPv4- als auch IPv6-Adressen zurückgegeben werden, müssen für die Verbindung zu diesen Zieladressen separate IPv4- und IPv6-Sockets verwendet werden. All diese Komplexität kann durch die Verwendung der Funktion WSAConnectByName unter Windows Vista und höher vermieden werden. Anwendungsentwickler*innen werden daher dazu angehalten, diese neue Funktion zu verwenden.

Das folgende Codebeispiel zeigt die richtige Reihenfolge, in der zuerst die Namensauflösung durchgeführt wird (in der vierten Zeile des folgenden Quellcodebeispiels) und dann ein Socket geöffnet wird (in der 19. Zeile des folgenden Codebeispiels). Dieses Beispiel ist ein Auszug aus der Datei Client.c, die Sie im IPv6-fähigen Client-Code in Anhang B finden. Die Funktion PrintError, die im folgenden Codebeispiel aufgerufen wird, ist im Beispiel Client.c aufgeführt.

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

SOCKET OpenAndConnect(char *Server, char *PortName, int Family, int SocketType)
{

    int iResult = 0;
    SOCKET ConnSocket = INVALID_SOCKET;

    ADDRINFO *AddrInfo = NULL;
    ADDRINFO *AI = NULL;
    ADDRINFO Hints;

    char *AddrName = NULL;

    memset(&Hints, 0, sizeof (Hints));
    Hints.ai_family = Family;
    Hints.ai_socktype = SocketType;

    iResult = getaddrinfo(Server, PortName, &Hints, &AddrInfo);
    if (iResult != 0) {
        printf("Cannot resolve address [%s] and port [%s], error %d: %s\n",
               Server, PortName, WSAGetLastError(), gai_strerror(iResult));
        return INVALID_SOCKET;
    }
    //
    // Try each address getaddrinfo returned, until we find one to which
    // we can successfully connect.
    //
    for (AI = AddrInfo; AI != NULL; AI = AI->ai_next) {

        // Open a socket with the correct address family for this address.
        ConnSocket = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
        if (ConnSocket == INVALID_SOCKET) {
            printf("Error Opening socket, error %d\n", WSAGetLastError());
            continue;
        }
        //
        // Notice that nothing in this code is specific to whether we 
        // are using UDP or TCP.
        //
        // When connect() is called on a datagram socket, it does not 
        // actually establish the connection as a stream (TCP) socket
        // would. Instead, TCP/IP establishes the remote half of the
        // (LocalIPAddress, LocalPort, RemoteIP, RemotePort) mapping.
        // This enables us to use send() and recv() on datagram sockets,
        // instead of recvfrom() and sendto().
        //

        printf("Attempting to connect to: %s\n", Server ? Server : "localhost");
        if (connect(ConnSocket, AI->ai_addr, (int) AI->ai_addrlen) != SOCKET_ERROR)
            break;

        if (getnameinfo(AI->ai_addr, (socklen_t) AI->ai_addrlen, AddrName,
                        sizeof (AddrName), NULL, 0, NI_NUMERICHOST) != 0) {
            strcpy_s(AddrName, sizeof (AddrName), "<unknown>");
            printf("connect() to %s failed with error %d\n", AddrName, WSAGetLastError());
            closesocket(ConnSocket);
            ConnSocket = INVALID_SOCKET;
        }    
    }
    return ConnSocket;
}

Funktionen des IP-Hilfsprogramms

Schließlich müssen Anwendungen, die die IP-Hilfsfunktion GetAdaptersInfo und die zugehörige Struktur IP_ADAPTER_INFO verwenden, beachten, dass sowohl diese Funktion als auch die Struktur auf IPv4-Adressen beschränkt sind. Die Funktion und die Struktur werden durch die Funktion GetAdaptersAddresses und die Struktur IP_ADAPTER_ADDRESSES ersetzt, die IPv6-fähig sind. IPv6-fähige Anwendungen, die die IP-Hilfs-API nutzen, sollten die Funktion GetAdaptersAddresses und die entsprechende IPv6-fähige Struktur IP_ADAPTER_ADDRESSES verwenden, die beide im Microsoft Windows Software Development Kit (SDK) definiert sind.

Empfehlungen

Die beste Methode, um sicherzustellen, dass Ihre Anwendung IPv6-kompatible Funktionsaufrufe verwendet, ist die Verwendung der Funktion getaddrinfo zum Abrufen der Host-Adressübersetzung. Ab Windows XP macht die Funktion getaddrinfo die Funktion gethostbyname überflüssig. In Ihrer Anwendung sollten Sie daher bei zukünftigen Programmierprojekten stattdessen die Funktion getaddrinfo verwenden. Auch wenn Microsoft die Funktion gethostbyname weiterhin unterstützt, wird diese Funktion nicht für IPv6 erweitert werden. Zur transparenten Unterstützung für das Abrufen von IPv6- und IPv4-Hostinformationen müssen Sie getaddrinfo verwenden.

Im folgenden Beispiel wird die optimale Verwendung der Funktion getaddrinfo veranschaulicht. Beachten Sie, dass die Funktion, wenn sie wie in diesem Beispiel richtig verwendet wird, sowohl die IPv6- als auch die IPv4-Host-Adressübersetzung richtig handhabt, aber auch andere nützliche Informationen über den Host abruft, wie z. B. den Typ der unterstützten Sockets. Dieses Beispiel ist ein Auszug aus dem Beispiel Client.c, das Sie in Anhang B finden.

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

int ResolveName(char *Server, char *PortName, int Family, int SocketType)
{

    int iResult = 0;

    ADDRINFO *AddrInfo = NULL;
    ADDRINFO *AI = NULL;
    ADDRINFO Hints;

   //
    // By not setting the AI_PASSIVE flag in the hints to getaddrinfo, we're
    // indicating that we intend to use the resulting address(es) to connect
    // to a service.  This means that when the Server parameter is NULL,
    // getaddrinfo will return one entry per allowed protocol family
    // containing the loopback address for that family.
    //
    
    memset(&Hints, 0, sizeof(Hints));
    Hints.ai_family = Family;
    Hints.ai_socktype = SocketType;
    iResult = getaddrinfo(Server, PortName, &Hints, &AddrInfo);
    if (iResult != 0) {
        printf("Cannot resolve address [%s] and port [%s], error %d: %s\n",
               Server, PortName, WSAGetLastError(), gai_strerror(iResult));
        return SOCKET_ERROR;
    }
     return 0;
}

Hinweis

Die Version der Funktion getaddrinfo, die IPv6 unterstützt, wird in der Windows XP-Version von Windows neu eingeführt.

 

Code, den es zu vermeiden gilt

Die Übersetzung von Hostadressen wurde bisher mit der Funktion gethostbyname durchgeführt. Ab Windows XP:

  • Die Funktion getaddrinfo macht die Funktion gethostbyname überflüssig.
  • Ihre Anwendungen sollten die Funktion getaddrinfo anstelle der Funktion gethostbyname verwenden.

Programmieraufgaben

So ändern Sie eine vorhandene IPv4-Anwendung, um Unterstützung für IPv6 hinzuzufügen

  1. Erwerben Sie das Hilfsprogramm Checkv4.exe. Dieses Hilfsprogramm wird als Teil des Windows SDK installiert. Eine ältere Version des Checkv4.exe-Tools war auch Bestandteil von Microsoft IPv6 Technology Preview für Windows 2000.
  2. Führen Sie das Hilfsprogramm Checkv4.exe gegen Ihren Code aus. Weitere Informationen zum Ausführen des Versionshilfsprogramms für Ihre Dateien finden Sie unter Verwenden des Hilfsprogramms Checkv4.exe.
  3. Das Hilfsprogramm benachrichtigt Sie über die Verwendung der Funktionen gethostbyname, gethostbyaddr und weiteren nur IPv4-fähigen Funktionen, und enthält Empfehlungen zum Ersetzen durch die IPv6-kompatible Funktion, z. B. getaddrinfo und getnameinfo.
  4. Ersetzen Sie alle Instanzen der Funktion gethostbyname und passen Sie den zugehörigen Code entsprechend an die Funktion getaddrinfo an. Verwenden Sie unter Windows Vista bei Bedarf die Funktion WSAConnectByName oder WSAConnectByList.
  5. Ersetzen Sie alle Instanzen der Funktion gethostbyaddr und passen Sie den entsprechenden Code an die Funktion getnameinfo an.

Alternativ können Sie Ihre Codebasis nach Instanzen der Funktionen gethostbyname und gethostbyaddr durchsuchen und diese Stellen (und ggf. anderen zugehörigen Code) durch die Funktionen getaddrinfo bzw. getnameinfo ersetzen.

IPv6-Leitfaden für Windows Sockets-Anwendungen

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

Dual-Stack-Sockets für IPv6-Winsock-Anwendungen

Verwenden von hartcodierten IPv4-Adressen

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

Zugrunde liegende Protokolle für IPv6-Winsock-Anwendungen