Поделиться через


Изменение структур данных для приложений Winsock для IPv6

При добавлении поддержки IPv6 необходимо убедиться, что приложение определяет структуры данных правильного размера. Размер IPv6-адреса гораздо больше, чем IPv4-адрес. Структуры, которые жестко закодируются для обработки размера IPv4-адреса при хранении IP-адреса, вызывают проблемы в приложении и должны быть изменены.

Лучшие практики

Лучший подход к обеспечению правильного размера структур заключается в использовании структуры SOCKADDR_STORAGE. Структура SOCKADDR_STORAGE не зависит от версии IP-адреса. Если структура SOCKADDR_STORAGE используется для хранения IP-адресов, IPv4 и IPv6-адреса можно правильно обрабатывать с помощью одной базы кода.

В следующем примере, который является фрагментом файла Server.c, найденного в приложении B, определяется соответствующее использование структуры 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 для хранения независимых от протокола адресов или структуры sockaddr_in для IP-адресов. Ни структура sockaddr, ни структура sockaddr_in не являются достаточно большими, чтобы хранить IPv6-адреса, и поэтому обе структуры недостаточно велики, если ваше приложение должно быть совместимо с IPv6.

Задача программирования

Модификация существующей базы кода для обеспечения совместимости с IPv4 и IPv6

  1. Получите программу Checkv4.exe. Эта программа включена в пакет SDK для Microsoft Windows.
  2. Запустите утилиту Checkv4.exe на вашем коде. Узнайте, как запустить программу Checkv4.exe для файлов в разделе "Использование служебной программы Checkv4.exe".
  3. Программа оповещает об использовании структур sockaddr или sockaddr_in и предоставляет рекомендации по их замене на структуру SOCKADDR_STORAGE, которая совместима с IPv6.
  4. Замените все такие экземпляры и соответствующий код на использование структуры SOCKADDR_STORAGE.

Кроме того, вы можете искать в кодовой базе случаи использования структур sockaddr и sockaddr_in и изменить все такие использования (а также другой связанный код, при необходимости) на структуру SOCKADDR_STORAGE.

Примечание.

Структуры addrinfo и SOCKADDR_STORAGE включают семейства протоколов и семейства адресов (ai_family и ss_family), соответственно. RFC 2553 указывает ai_family член addrinfo как int, а ss_family указывается как short; поэтому прямая копия между этими членами приводит к ошибке компилятора.

 

Руководство по IPv6 для приложений сокетов Windows

Сокеты с двойным стеком для приложений Winsock IPv6

Вызовы функций для приложений Winsock IPv6

Использование жестких IPv4-адресов

Проблемы с пользовательским интерфейсом для приложений Winsock IPv6

Базовые протоколы для приложений Winsock IPv6