You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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;
}

关键修正点说明

  1. 添加Winsock初始化:调用WSAStartup和WSACleanup,确保网络相关函数(如inet_ntop)正常工作。
  2. IPv6地址转换函数:实现ipv6ToString,用inet_ntop将16字节二进制地址转换为标准IPv6字符串格式(如2001:db8::1)。
  3. 修复缓冲区大小逻辑:移除错误的dwSize3,直接使用dwSize2(DWORD类型)来调整缓冲区大小,避免溢出。
  4. 修正打印逻辑:使用转换后的字符串打印IPv6地址,用方括号包裹符合IPv6地址的表示规范,端口转换保持正确的字节序。
  5. 修复语法错误:修正printf的分隔线字符串,移除重复的头文件包含。

内容的提问来源于stack exchange,提问作者Ahmad.s

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:35:27