變更 IPv6 Winsock Appications 的數據結構
新增對 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 結構來儲存與通訊協定無關的位址,或 IP位址的sockaddr_in 結構。 sockaddr 結構或 sockaddr_in 結構都不夠大,無法保存 IPv6 位址,因此如果您的應用程式與 IPv6 相容,兩者都不足。
編碼工作
將現有的程式代碼基底從IPv4修改為IPv4和IPv6互操作性
- 取得Checkv4.exe公用程式。 公用程式隨附於 Microsoft Windows 軟體開發工具包 (SDK) 中。
- 針對您的程式代碼執行Checkv4.exe公用程式。 瞭解如何在使用 Checkv4.exe 公用程式一節 中,對檔案執行 Checkv4.exe 公用程式。
- 公用程式會 警示您使用sockaddr 或 sockaddr_in 結構,並提供如何以IPv6相容結構 取代SOCKADDR_STORAGE的建議。
- 視需要取代任何這類實例和相關聯的程序代碼,以使用 SOCKADDR_STORAGE 結構。
或者,您可以搜尋您的程式代碼基底來尋找 sockaddr 和 sockaddr_in 結構的實例,並視需要將所有這類使用方式(以及其他相關聯的程式代碼)變更為 SOCKADDR_STORAGE 結構。
注意
addrinfo 和 SOCKADDR_STORAGE 結構分別包括通訊協議和位址家庭成員(ai_family和ss_family)。 RFC 2553 會將 addrinfo ai_family 成員指定為 int,而ss_family指定為簡短;因此,這些成員之間的直接複製會導致編譯程序錯誤。
相關主題