如何在Windows中显示当前IPv6连接?代码遇地址不显示问题
解决GetExtendedTcpTable获取IPv6地址无输出的问题
问题分析
你的代码存在几个关键问题导致无法正确显示IPv6地址:
- IPv6地址打印方式错误:
ucLocalAddr和ucRemoteAddr是16字节的二进制数组,直接用cout或printf("%s")会把它当作C风格字符串处理,而二进制数据并非可打印字符串,自然看不到正确地址。必须用专门的函数将二进制IPv6地址转换为标准字符串格式。 - 缓冲区大小类型错误:
dwSize3被定义为UCHAR类型,当所需缓冲区大小超过255字节时,会因溢出导致缓冲区分配不足,可能丢失部分数据。 - 代码语法错误:
printf的分隔线字符串里直接换行,会导致编译失败;头文件重复包含且有格式错误。 - 地址输出逻辑错误:重复输出同一地址变量四次,完全不符合IPv6地址的格式要求。
修正后的代码
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include <ws2tcpip.h> #include <iphlpapi.h> #include <iostream> #include <vector> #include <in6addr.h> #include <Ws2ipdef.h> #pragma comment(lib,"psapi") #pragma comment(lib,"iphlpapi") #pragma comment(lib,"wsock32") #pragma comment(lib, "ws2_32.lib") using namespace std; // 辅助函数:将二进制IPv6地址转换为字符串 string ipv6ToString(const UCHAR* addr) { char str[INET6_ADDRSTRLEN] = {0}; in6_addr ipv6Addr; memcpy(&ipv6Addr, addr, sizeof(in6_addr)); inet_ntop(AF_INET6, &ipv6Addr, str, INET6_ADDRSTRLEN); return string(str); } int main() { WSADATA wsaData; // 初始化Winsock,否则inet_ntop可能无法正常工作 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { cerr << "WSAStartup failed" << endl; return 1; } vector<unsigned char> buffer2; DWORD dwSize2 = sizeof(MIB_TCP6TABLE_OWNER_PID); DWORD dwRetValue2 = 0; do { buffer2.resize(dwSize2, 0); dwRetValue2 = GetExtendedTcpTable(buffer2.data(), &dwSize2, TRUE, AF_INET6, TCP_TABLE_OWNER_PID_ALL, 0); } while (dwRetValue2 == ERROR_INSUFFICIENT_BUFFER); if (dwRetValue2 == ERROR_SUCCESS) { PMIB_TCP6TABLE_OWNER_PID ptTable = reinterpret_cast<PMIB_TCP6TABLE_OWNER_PID>(buffer2.data()); cout << "Number of Entries: " << ptTable->dwNumEntries << endl << endl; for (DWORD i = 0; i < ptTable->dwNumEntries; i++) { cout << "--------------------------------" << endl; cout << "PID: " << ptTable->table[i].dwOwningPid << endl; cout << "State: " << ptTable->table[i].dwState << endl; // 转换并打印本地IPv6地址和端口 string localIp = ipv6ToString(ptTable->table[i].ucLocalAddr); unsigned short localPort = htons(ptTable->table[i].dwLocalPort); cout << "Local: [" << localIp << "]:" << localPort << endl; // 转换并打印远程IPv6地址和端口 string remoteIp = ipv6ToString(ptTable->table[i].ucRemoteAddr); unsigned short remotePort = htons(ptTable->table[i].dwRemotePort); cout << "Remote: [" << remoteIp << "]:" << remotePort << endl; cout << endl; } } else { cerr << "GetExtendedTcpTable failed with error: " << dwRetValue2 << endl; } WSACleanup(); cin.get(); return 0; }
关键修正点说明
- 添加Winsock初始化:调用
WSAStartup和WSACleanup,确保网络相关函数(如inet_ntop)正常工作。 - IPv6地址转换函数:实现
ipv6ToString,用inet_ntop将16字节二进制地址转换为标准IPv6字符串格式(如2001:db8::1)。 - 修复缓冲区大小逻辑:移除错误的
dwSize3,直接使用dwSize2(DWORD类型)来调整缓冲区大小,避免溢出。 - 修正打印逻辑:使用转换后的字符串打印IPv6地址,用方括号包裹符合IPv6地址的表示规范,端口转换保持正确的字节序。
- 修复语法错误:修正
printf的分隔线字符串,移除重复的头文件包含。
内容的提问来源于stack exchange,提问作者Ahmad.s
相关产品推荐
相关产品推荐

