寻找应用程序使用的TCP端口

12

好的,我正在扩展公司的Flexlm供应商守护进程,以使其对客户端应用程序更加透明。

在客户端连接之前,我需要能够找到lmgrd正在侦听的端口。API文档似乎相当贫瘠,而且我认为他们将大部分代码编译成一种形式,因此我不能仅仅查看他们的源代码。

是否可以调用Windows API的强大功能来查找特定进程正在使用的端口?如果 Sysinternals 的 Process Explorer 可以做到,我也应该能够做到,对吧?这方面的示例代码是什么?

它需要支持 Windows XP 及更高版本,因为我们的许多客户尚未升级。

需要注意的是,事实证明FLEX支持从许可证文件中获取端口。我手头没有代码,但是我知道这不是找出您的供应商守护程序/lmgrd正在运行的端口的最佳方法。

3个回答

10

GetTcpTable2 -- 请参见下文

GetTcpTable2函数

GetTcpTable函数用于检索IPv4 TCP连接表。

此函数将填充MIB_TCPTABLE结构。

typedef struct _MIB_TCPTABLE {
  DWORD      dwNumEntries;
  MIB_TCPROW table[ANY_SIZE];
} MIB_TCPTABLE, *PMIB_TCPTABLE;

现在我们来看一下MIB_TCPROW

typedef struct _MIB_TCPROW {
  DWORD dwState;
  DWORD dwLocalAddr;
  DWORD dwLocalPort;
  DWORD dwRemoteAddr;
  DWORD dwRemotePort;
} MIB_TCPROW, *PMIB_TCPROW;

重要提示:

为了获取相应的PID关联,您需要使用GetTcpTable2。

typedef struct _MIB_TCPROW2 {
  DWORD                        dwState;
  DWORD                        dwLocalAddr;
  DWORD                        dwLocalPort;
  DWORD                        dwRemoteAddr;
  DWORD                        dwRemotePort;
  DWORD                        dwOwningPid;
  TCP_CONNECTION_OFFLOAD_STATE dwOffloadState;
} MIB_TCPROW2, *PMIB_TCPROW2;

dwOwningPid


糟糕,做不到。GetTcpTable2 函数似乎是Vista及更高版本的函数。我应该明确指定它应该至少在Windows XP上工作,因为我们的许多客户尚未升级。我会更新我的原始帖子。不过你找到的真不错,必须得说。 - RandomInsano
所以...看起来最接近的Windows XP版本是AllocateAndGetTcpExTableFromStack http://msdn.microsoft.com/en-us/library/aa365804(v=vs.85).aspx - RandomInsano
1
应使用GetTcpTable或GetExtendedTcpTable函数来检索TCP连接表,而不是使用AllocateAndGetTcpExTableFromStack函数。注意:AllocateAndGetTcpExTableFromStack函数已被弃用,在Windows Vista及更高版本上不受支持。在发布给Windows Vista及更高版本的Microsoft Windows软件开发工具包(SDK)中,AllocateAndGetTcpExTableFromStack的函数原型仍在Iphlpapi.h头文件中定义,以继续支持Windows Server 2003和Windows XP。 - flumpb
1
使用:GetExtendedTcpTable和GetOwnerModuleFromTcpEntry。 - flumpb
刚刚发现了GetExtendedTcpTable。太棒了! - RandomInsano
这个似乎悬空的 "dwOwningPid" 是什么意思?它是 _MIB_TCPROW2 字段中的一个。 - Peter Mortensen

9
以下是我最终得出的代码,供之后遇到此问题的人参考:
#include "stdafx.h"
#include <windows.h>
#include <iphlpapi.h>

// These are just for the ntohl function in the printf below
#include <winsock.h>
#pragma comment(lib, "Ws2_32.lib")

DWORD (WINAPI *pGetExtendedTcpTable)(
  PVOID pTcpTable,
  PDWORD pdwSize,
  BOOL bOrder,
  ULONG ulAf,
  TCP_TABLE_CLASS TableClass,
  ULONG Reserved
);

int _tmain(int argc, _TCHAR* argv[])
{
    MIB_TCPTABLE_OWNER_PID *pTCPInfo;
    MIB_TCPROW_OWNER_PID *owner;
    DWORD size;
    DWORD dwResult;

    HMODULE hLib = LoadLibrary("iphlpapi.dll");

    pGetExtendedTcpTable = (DWORD (WINAPI *)(PVOID, PDWORD, BOOL, ULONG, TCP_TABLE_CLASS, ULONG))
        GetProcAddress(hLib, "GetExtendedTcpTable");

    if (!pGetExtendedTcpTable)
    {
        printf("Could not load iphlpapi.dll. This application is for Windows XP SP2 and up.\n");
        return 1;
    }

    dwResult = pGetExtendedTcpTable(NULL,     &size, false, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0);
    pTCPInfo = (MIB_TCPTABLE_OWNER_PID*)malloc(size);
    dwResult = pGetExtendedTcpTable(pTCPInfo, &size, false, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0);

    if (dwResult != NO_ERROR)
    {
        printf("Couldn't get our IP table");
        return 2;
    }

    printf("Iterating though table:\n");
    for (DWORD dwLoop = 0; dwLoop < pTCPInfo->dwNumEntries; dwLoop++)
    {
        owner = &pTCPInfo->table[dwLoop];

        printf("  PID: %5u - Port: %5u\n", owner->dwOwningPid, ntohs(owner->dwLocalPort));
    }

    // Pause a moment
    printf("Done Processing\n");

    return 0;
}

3

在最坏的情况下,您总是可以解析以下输出:

netstat -bna

有趣的想法。需要找到该应用程序的反向工程版本。我偶然发现了旧的Winternals源代码,将研究那位开发者如何实现他的TCPView应用程序。 - RandomInsano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接