首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

IPv6 下 VC++ 網路程式設計實戰(二):Windows 平台完整範例

     編輯:VC 教學

IPv4 vs IPv6 關鍵差異速查

項目IPv4IPv6
位址長度32 bits128 bits
位址結構sockaddr_in + in_addrsockaddr_in6 + in6_addr
字串轉位址inet_aton/inet_ntoainet_pton/inet_ntop (通用)
名稱解析gethostbynamegetaddrinfo (通用、功能更強)
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); // 記得釋放

Windows 2000 + IPv6 Tech Preview 完整範例

環境:Win2K SP3 + tpipv6-001205-SP3-IE6 + VC6
注意:Win2K IPv6 為預覽版,recvfrom 有已知問題,範例改用 recv;正式開發請用 XP/Linux。

1. 頭文件與庫

#include 
#include 
#include "tpipv6.h"  // Tech Preview 頭文件
#pragma comment(lib, "ws2_32.lib")

2. 建立 Socket 並綁定(異步模式)

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);

3. 發送資料

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);

4. 異步接收處理(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;
}

IP 無關寫法提示(下一篇主題)

  • 全部用 AF_UNSPEC + getaddrinfo,回傳鏈表含 IPv4/IPv6 混合位址;
  • 遍歷 res 鏈表嘗試 socket/connect 直到成功;
  • 儲存 sockaddr_storage 統一容納兩種結構;
  • 避免硬編碼 AF_INET/AF_INET6、結構體大小、位址字串格式。

常見坑點

  • sin6_scope_id:連結本地址(fe80::)必須指定介面索引,否則無法路由;
  • WSAAddressToString 格式化輸出時需傳正確結構大小;
  • 防火牆/路由器需開啟 IPv6 通道(Teredo/6to4/原生);
  • VC6 需額外引入 tpipv6.h,VS2010+ 內建完整 IPv6 SDK。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved