| 項目 | IPv4 | IPv6 |
|---|---|---|
| 位址長度 | 32 bits | 128 bits |
| 位址結構 | sockaddr_in + in_addr | sockaddr_in6 + in6_addr |
| 字串轉位址 | inet_aton/inet_ntoa | inet_pton/inet_ntop (通用) |
| 名稱解析 | gethostbyname | getaddrinfo (通用、功能更強) |
| Socket API | 專用 | socket/bind/send/recv/accept/listen **不變** |
getaddrinfo 一站式解析addrinfo hints = {}, *res = NULL;
hints.ai_family = AF_INET6; // 強制 IPv6,或 AF_UNSPEC 由系統決定
hints.ai_socktype = SOCK_DGRAM; // UDP
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_NUMERICHOST; // 直接用數字 IP
int rc = getaddrinfo(ipStr, portStr, &hints, &res);
if (rc != 0) { /* 錯誤處理 */ }
SOCKET s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(s, res->ai_addr, res->ai_addrlen);
// 後續 sendto/recvfrom 直接用 res->ai_addr
freeaddrinfo(res); // 記得釋放
環境:Win2K SP3 + tpipv6-001205-SP3-IE6 + VC6
注意:Win2K IPv6 為預覽版,recvfrom 有已知問題,範例改用 recv;正式開發請用 XP/Linux。
#include
#include
#include "tpipv6.h" // Tech Preview 頭文件
#pragma comment(lib, "ws2_32.lib")
addrinfo hints = {}, *res = NULL;
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_NUMERICHOST;
CString localIP = m_sendIP; // 本機 IP
getaddrinfo(localIP, _T("2000"), &hints, &res);
SOCKET s_send = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(s_send, res->ai_addr, res->ai_addrlen);
// 異步選擇:FD_READ 觸發 UM_PACKET 訊息
WSAAsyncSelect(s_send, m_hWnd, UM_PACKET, FD_READ);
addrinfo hints = {}, *res = NULL;
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_NUMERICHOST;
CString remoteIP = m_receiveIP;
getaddrinfo(remoteIP, _T("2000"), &hints, &res);
sendto(s_send, sendBuf, sendLen, 0, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
WM_TIMER / UM_PACKET)LRESULT CMyDlg::OnPacket(WPARAM wParam, LPARAM lParam) {
char buf[128] = {0};
sockaddr_in6 sa = {}; int saLen = sizeof(sa);
// Win2K 用 recv,標準平台用 recvfrom
int len = recv(s_send, buf, sizeof(buf)-1, 0);
if (len <= 0) return 0;
buf[len] = '\0';
CString msg; msg.Format(_T("Recved: %s"), buf);
m_list.AddString(msg); // 列表顯示
return 0;
}
AF_UNSPEC + getaddrinfo,回傳鏈表含 IPv4/IPv6 混合位址;res 鏈表嘗試 socket/connect 直到成功;sockaddr_storage 統一容納兩種結構;AF_INET/AF_INET6、結構體大小、位址字串格式。sin6_scope_id:連結本地址(fe80::)必須指定介面索引,否則無法路由;WSAAddressToString 格式化輸出時需傳正確結構大小;tpipv6.h,VS2010+ 內建完整 IPv6 SDK。