更改 IPv6 Winsock 应用的数据结构

添加对 IPv6 的支持时,必须确保应用程序定义大小正确的数据结构。 IPv6 地址的大小比 IPv4 地址大得多。 在存储 IP 地址时硬编码以处理 IPv4 地址大小的结构将导致应用程序中出现问题,必须对其进行修改。

最佳做法

确保正确调整结构大小的最佳方法是使用 SOCKADDR_STORAGE 结构。 SOCKADDR_STORAGE结构与 IP 地址版本无关。 使用 SOCKADDR_STORAGE 结构存储 IP 地址时,可以使用一个代码库正确处理 IPv4 和 IPv6 地址。

以下示例摘自附录 B 中 Server.c 文件的摘录,标识了 SOCKADDR_STORAGE 结构的相应用法。 请注意,如果结构正确使用,如本示例所示,可正常处理 IPv4 或 IPv6 地址。

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

#pragma comment(lib, "Ws2_32.lib")

#define BUFFER_SIZE 512
#define DEFAULT_PORT "27015"

int main(int argc, char **argv)
{
    char Buffer[BUFFER_SIZE] = {0};
    char *Hostname;
    int Family = AF_UNSPEC;
    int SocketType = SOCK_STREAM;
    char *Port = DEFAULT_PORT;
    char *Address = NULL;
    int i = 0;
    DWORD dwRetval = 0;
    int iResult = 0;
    int FromLen = 0;
    int AmountRead = 0;

    SOCKADDR_STORAGE From;

    WSADATA wsaData;

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

    // Parse arguments
    if (argc >= 1) {
        Hostname = argv[1];
    }    

   // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

    From.ss_family = (ADDRESS_FAMILY) Family;
    
    //...
        
        return 0;
}

注意

SOCKADDR_STORAGE结构是 Windows XP 的新增功能。

 

要避免的代码

通常,许多应用程序使用 sockaddr 结构来存储与协议无关的地址或 IP 地址的 sockaddr_in 结构。 sockaddr 结构和 sockaddr_in 结构都不够大,无法容纳 IPv6 地址,因此,如果应用程序要与 IPv6 兼容,则两者都是不够的。

编码任务

将现有代码库从 IPv4 修改为 IPv4 和 IPv6 互操作性

  1. 获取Checkv4.exe实用工具。 该实用工具包含在 Microsoft Windows 软件开发工具包 (SDK) 中,可通过 MSDN 订阅或从 Web 下载。
  2. 针对代码运行 Checkv4.exe 实用工具。 了解如何使用 Checkv4.exe 实用工具部分针对文件运行 Checkv4.exe 实用工具
  3. 实用工具会提醒你使用 sockaddrsockaddr_in 结构,并提供有关如何将任一结构替换为 IPv6 兼容结构 SOCKADDR_STORAGE的建议。
  4. 根据需要替换任何此类实例和关联的代码,以使用 SOCKADDR_STORAGE 结构。

或者,可以在代码库中搜索 sockaddrsockaddr_in 结构的实例,并根据需要) SOCKADDR_STORAGE结构更改 所有此类用法 (和其他关联代码。

注意

addrinfoSOCKADDR_STORAGE 结构分别包括协议和地址系列成员 (ai_familyss_family) 。 RFC 2553 将 addrinfo的 ai_family 成员指定为 int,而 ss_family 指定为 short;因此,这些成员之间的直接复制会导致编译器错误。

 

适用于 Windows 套接字应用程序的 IPv6 指南

适用于 IPv6 Winsock 应用程序的双堆栈套接字

IPv6 Winsock 应用程序的函数调用

使用硬编码的 IPv4 地址

IPv6 Winsock 应用程序的用户界面问题

IPv6 Winsock 应用程序的基础协议