c++ 如何显示当前的IPv6连接?

up9lanfz  于 2022-12-20  发布在  其他
关注(0)|答案(1)|浏览(142)

我一直试图从Windows中使用GetExtendedTcpTable()方法显示当前的IPv6连接,但我没有让它显示任何IPv6地址。
我只找到了有关如何显示当前IPv4连接的代码,因此我所做的是将Windows文档中的IPv4方法更改为IPv6方法。
我也试过其他方法,比如PMIB_TCP6ROW_OWNER_MODULE,但它就是不会显示IPv6地址。
有关PID的信息保存在ptTable中,但ucLocalAddrusRemoteAddr未返回任何内容。
代码如下所示:

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <ws2tcpip.h> 
#include <iphlpapi.h>
#include <iostream>
#include <vector>
#include <in6addr.h>
#include <Ws2ipdef.h>
#include < ws2tcpip.h>

#pragma comment(lib,"psapi")
#pragma comment(lib,"iphlpapi")
#pragma comment(lib,"wsock32")
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

using namespace std;

int main()
{

vector<unsigned char> buffer2;
DWORD dwSize2 = sizeof(MIB_TCP6TABLE_OWNER_PID);
UCHAR dwSize3 = sizeof(MIB_TCP6TABLE_OWNER_PID);
DWORD dwRetValue2 = 0;

do
{
    buffer2.resize(dwSize3, 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;

    // caution: array starts with index 0, count starts by 1
    for (DWORD i = 0; i < ptTable->dwNumEntries; i++)
    {

        DWORD pid = ptTable->table[i].dwOwningPid;
        UCHAR* lol = ptTable->table[i].ucLocalAddr;
        printf("%s", "--------------------------------\n");
        printf("%s", ptTable->table[i].ucLocalAddr);

            cout << "PID: " << ptTable->table[i].dwOwningPid << endl;
            cout << "State: " << ptTable->table[i].dwState << endl;
            cout << "Local: "
                << (ptTable->table[i].ucLocalAddr)                                               
                << ":"
                << ((ptTable->table[i].ucLocalAddr))
                << ":"
                << ((ptTable->table[i].ucLocalAddr))
                << ":"
                << ((ptTable->table[i].ucLocalAddr))
                << ":"
                << htons((unsigned short)ptTable->table[i].dwLocalPort)
                << endl;

            cout << "Remote: "
                << (ptTable->table[i].ucRemoteAddr)
                << ":"
                << ((ptTable->table[i].ucRemoteAddr))
                << ":"
                << ((ptTable->table[i].ucRemoteAddr))
                << ":"
                << ((ptTable->table[i].ucRemoteAddr))
                << ":"
                << htons((unsigned short)ptTable->table[i].dwRemotePort)
                << endl;

            cout << endl;
        }
    }

    cin.get();
}
hfyxw5xn

hfyxw5xn1#

您的do循环没有正确地扩展vector,它在每次迭代时都会将vector的大小调整为相同的值。请删除dwSize3,并使用dwSize2来调整大小和枚举。
此外,由于您正在检索AF_INET6条目,表中的每个IPv6地址的大小为16字节,但您甚至无法正确显示任何字节。IP地址以原始字节而不是字符串的形式提供。幸运的是,API具有用于该转换的函数,如documentation
ucLocalAddr和ucRemoteAddr成员按网络字节顺序存储在字符数组中。RtlIpv6AddressToString或RtlIpv6AddressToStringEx函数可用于将ucLocalAddr或ucRemoteAddr成员中的IPv6地址转换为字符串,而无需加载Windows套接字DLL。
试试这样的方法:

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <ws2tcpip.h> 
#include <iphlpapi.h>
#include <iostream>
#include <vector>
#include <in6addr.h>
#include <Ws2ipdef.h>
#include <ws2tcpip.h>
#include <Mstcpip.h>

#pragma comment(lib, "psapi")
#pragma comment(lib, "iphlpapi")
#pragma comment(lib, "wsock32")
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

using namespace std;

int main()
{
    vector<BYTE> buffer;
    DWORD dwSize = sizeof(MIB_TCP6TABLE_OWNER_PID);
    DWORD dwRetValue = 0;

    in6_addr in6_localAddr, in6_remoteAddr; 
    char szLocalAddr[INET6_ADDRSTRLEN], szRemoteAddr[INET6_ADDRSTRLEN];
    ULONG ulAddrLen;

    do
    {
        buffer.resize(dwSize, 0);
        dwRetValue = GetExtendedTcpTable(buffer.data(), &dwSize, TRUE, AF_INET6, TCP_TABLE_OWNER_PID_ALL, 0);
    
    } while (dwRetValue == ERROR_INSUFFICIENT_BUFFER);

    if (dwRetValue == ERROR_SUCCESS)
    {
        PMIB_TCP6TABLE_OWNER_PID ptTable = reinterpret_cast<PMIB_TCP6TABLE_OWNER_PID>(buffer.data());

        cout << "Number of Entries: " << ptTable->dwNumEntries << endl << endl;

        for (DWORD i = 0; i < ptTable->dwNumEntries; i++)
        {
            memcpy(&in6_localAddr.u.Byte, ptTable->table[i].ucLocalAddr, 16);
            memcpy(&in6_remoteAddr.u.Byte, ptTable->table[i].ucRemoteAddr, 16);

            ulAddrLen = INET6_ADDRSTRLEN;
            RtlIpv6AddressToStringExA(&in6_localAddr, ptTable->table[i].dwLocalScopeId, ptTable->table[i].dwLocalPort, szLocalAddr, &ulAddrLen);

            ulAddrLen = INET6_ADDRSTRLEN;
            RtlIpv6AddressToStringExA(&in6_remoteAddr, ptTable->table[i].dwRemoteScopeId, ptTable->table[i].dwRemotePort, szRemoteAddr, &ulAddrLen);

            cout << "--------------------------------\n";

            cout << "PID: " << ptTable->table[i].dwOwningPid << endl;
            cout << "State: " << ptTable->table[i].dwState << endl;
            cout << "Local: " << szLocalAddr << endl;
            cout << "Remote: " << szRemoteAddr << endl;

            cout << endl;
        }
    }

    cin.get();
}

相关问题