Loading

获取Windows下某进程监听的TCP/UDP端口

1、在Windows下用CMD netstat命令可以获得当前进程监听端口号的信息,如netstat -ano可以看到IP、port、状态和监听的PID。

那么可以执行CMD这个进程得到监听的端口号信息,C#代码如下:

            //进程id
            int pid = ProcInfo.ProcessID;
            
            //存放进程使用的端口号链表
            List<int> ports = new List<int>();

            Process pro = new Process();
            pro.StartInfo.FileName = "cmd.exe";
            pro.StartInfo.UseShellExecute = false;
            pro.StartInfo.RedirectStandardInput = true;
            pro.StartInfo.RedirectStandardOutput = true;
            pro.StartInfo.RedirectStandardError = true;
            pro.StartInfo.CreateNoWindow = true;
            pro.Start();
            pro.StandardInput.WriteLine("netstat -ano");
            pro.StandardInput.WriteLine("exit");
            Regex reg = new Regex("\\s+", RegexOptions.Compiled);
            string line = null;
            ports.Clear();
            while ((line = pro.StandardOutput.ReadLine()) != null)
            {
                line = line.Trim();
                if (line.StartsWith("TCP", StringComparison.OrdinalIgnoreCase))
                {
                    line = reg.Replace(line, ",");
                    string[] arr = line.Split(',');
                    if (arr[4] == pid.ToString())
                    {
                        string soc = arr[1];
                        int pos = soc.LastIndexOf(':');
                        int pot = int.Parse(soc.Substring(pos + 1));
                        ports.Add(pot);
                    }
                }
                else if (line.StartsWith("UDP", StringComparison.OrdinalIgnoreCase))
                {
                    line = reg.Replace(line, ",");
                    string[] arr = line.Split(',');
                    if (arr[3] == pid.ToString())
                    {
                        string soc = arr[1];
                        int pos = soc.LastIndexOf(':');
                        int pot = int.Parse(soc.Substring(pos + 1));
                        ports.Add(pot);
                    }
                }
            }
            pro.Close();

2、如果不执行CMD进程,如何获得?可以参考这篇文章http://www.cnblogs.com/BoyXiao/archive/2012/02/20/2359273.html

文章介绍了使用Windows API获得进程和端口的映射关系:

(1)根据进程 ID 获得该进程所打开的所有的 TCP 和 UDP 端口。

(2)根据端口号来获得打开该端口的进程。

C语言代码如下:

// ProcessorPort.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"

#include <Windows.h>   
#include <Psapi.h>   
#include <Iprtrmib.h>   
#include <Winsock2.h>

#pragma  comment(lib,"Psapi.lib")
#pragma  comment(lib,"Iphlpapi.Lib")
#pragma  comment(lib,"WS2_32.lib")

enum TcpOrUdp
{
    TcpType,   
    UdpType  
};

typedef struct  
{  
    DWORD dwState;      //连接状态   
    DWORD dwLocalAddr;  //本地地址   
    DWORD dwLocalPort;  //本地端口   
    DWORD dwRemoteAddr; //远程地址   
    DWORD dwRemotePort; //远程端口   
    DWORD dwProcessId;  //进程标识 
}MIB_TCPEXROW,*PMIB_TCPEXROW;  


typedef struct  
{  
    DWORD dwLocalAddr;  //本地地址   
    DWORD dwLocalPort;  //本地端口   
    DWORD dwProcessId;  //进程标识   

}MIB_UDPEXROW,*PMIB_UDPEXROW;  


typedef struct  
{  
    DWORD dwState;      //连接状态   
    DWORD dwLocalAddr;  //本地地址   
    DWORD dwLocalPort;  //本地端口   
    DWORD dwRemoteAddr; //远程地址   
    DWORD dwRemotePort; //远程端口   
    DWORD dwProcessId;  //进程标识   
    DWORD Unknown;      //待定标识
}MIB_TCPEXROW_VISTA,*PMIB_TCPEXROW_VISTA;  


typedef struct  
{  
    DWORD dwNumEntries;  
    MIB_TCPEXROW table[ANY_SIZE];
}MIB_TCPEXTABLE,*PMIB_TCPEXTABLE;  


typedef struct  
{  
    DWORD dwNumEntries;  
    MIB_TCPEXROW_VISTA table[ANY_SIZE];
}MIB_TCPEXTABLE_VISTA,*PMIB_TCPEXTABLE_VISTA;  


typedef struct  
{  
    DWORD dwNumEntries;  
    MIB_UDPEXROW table[ANY_SIZE];
}MIB_UDPEXTABLE,*PMIB_UDPEXTABLE;  


//=====================================================================================//   
//Name: DWORD AllocateAndGetTcpExTableFromStack()                                      //                                                                //   
//Descripion: 该函数仅仅只在 Windows XP,Windows Server 2003 下有效                    //   
//=====================================================================================//   
typedef DWORD (WINAPI *PFNAllocateAndGetTcpExTableFromStack)(  
    PMIB_TCPEXTABLE *pTcpTabel,  
    bool bOrder,  
    HANDLE heap,  
    DWORD zero,  
    DWORD flags  
    );  

//=====================================================================================//   
//Name: DWORD AllocateAndGetUdpExTableFromStack()                                      //   
//Descripion: 该函数仅仅只在 XP,Windows Server 2003 下有效                            //   
//=====================================================================================//   
typedef DWORD (WINAPI *PFNAllocateAndGetUdpExTableFromStack)(  
    PMIB_UDPEXTABLE *pUdpTable,  
    bool bOrder,  
    HANDLE heap,  
    DWORD zero,  
    DWORD flags  
    );  

//=====================================================================================//   
//Name: DWORD InternalGetTcpTable2()                                                   //   
//Descripion: 该函数在 Windows Vista 以及 Windows 7 下面效                             //   
//=====================================================================================//   
typedef DWORD (WINAPI *PFNInternalGetTcpTable2)(  
    PMIB_TCPEXTABLE_VISTA *pTcpTable_Vista,  
    HANDLE heap,  
    DWORD flags  
    );  

//=====================================================================================//   
//Name: DWORD InternalGetUdpTableWithOwnerPid()                                        //   
//Descripion: 该函数在 Windows Vista 以及 Windows 7 下面效                             //   
//=====================================================================================//   
typedef DWORD (WINAPI *PFNInternalGetUdpTableWithOwnerPid)(  
    PMIB_UDPEXTABLE *pUdpTable,  
    HANDLE heap,  
    DWORD flags  
    );  


//=====================================================================================//   
//Name: DWORD GetProcessIdByPort()                                                     //   
//Descripion: 根据端口号得到打开该端口号的进程ID(支持 XP,Server 2003,Vista,Win7)   //   
//=====================================================================================//   
extern "C" __declspec(dllexport) DWORD __stdcall GetProcessIdByPort(TcpOrUdp type, DWORD dwPort)  
{  
    HMODULE hModule = LoadLibraryW(L"iphlpapi.dll");  
    if (hModule == NULL)  
    {  
        return 0;  
    }  

    if(type == TcpType)  
    {  
        // 表明查询的是 TCP 信息   
        PFNAllocateAndGetTcpExTableFromStack pAllocateAndGetTcpExTableFromStack;  
        pAllocateAndGetTcpExTableFromStack =   
            (PFNAllocateAndGetTcpExTableFromStack)GetProcAddress(hModule, "AllocateAndGetTcpExTableFromStack");  
        if (pAllocateAndGetTcpExTableFromStack != NULL)  
        {  
            // 表明为 XP 或者 Server 2003 操作系统   
            PMIB_TCPEXTABLE pTcpExTable = NULL;  
            if (pAllocateAndGetTcpExTableFromStack(&pTcpExTable, TRUE, GetProcessHeap(), 0, AF_INET) != 0)  
            {  
                if (pTcpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                }  

                FreeLibrary(hModule);  
                hModule = NULL;  

                return 0;  
            }  

            for (UINT i = 0; i < pTcpExTable->dwNumEntries; i++)  
            {  
                // 过滤掉数据,只查询我们需要的进程数据   
                if(dwPort == ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort))  
                {  
                    DWORD dwProcessId = pTcpExTable->table[i].dwProcessId;  
                    if (pTcpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                    }  

                    FreeLibrary(hModule);  
                    hModule = NULL;  

                    return dwProcessId;  
                }  
            }  

            if (pTcpExTable)  
            {  
                HeapFree(GetProcessHeap(), 0, pTcpExTable);  
            }  

            FreeLibrary(hModule);  
            hModule = NULL;  

            return 0;  
        }  
        else  
        {  
            // 表明为 Vista 或者 7 操作系统   
            PMIB_TCPEXTABLE_VISTA pTcpExTable = NULL;  
            PFNInternalGetTcpTable2 pInternalGetTcpTable2 =   
                (PFNInternalGetTcpTable2)GetProcAddress(hModule, "InternalGetTcpTable2");  
            if (pInternalGetTcpTable2 == NULL)  
            {  
                if (pTcpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                }  

                FreeLibrary(hModule);  
                hModule = NULL;  

                return 0;  
            }  

            if (pInternalGetTcpTable2(&pTcpExTable, GetProcessHeap(), 1))  
            {  
                if (pTcpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                }  

                FreeLibrary(hModule);  
                hModule = NULL;  

                return 0;  
            }  

            for (UINT i = 0;i < pTcpExTable->dwNumEntries; i++)  
            {  
                // 过滤掉数据,只查询我们需要的进程数据   
                if(dwPort == ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort))  
                {  
                    DWORD dwProcessId = pTcpExTable->table[i].dwProcessId;  
                    if (pTcpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                    }  

                    FreeLibrary(hModule);  
                    hModule = NULL;  

                    return dwProcessId;  
                }  
            }  

            if (pTcpExTable)  
            {  
                HeapFree(GetProcessHeap(), 0, pTcpExTable);  
            }  

            FreeLibrary(hModule);  
            hModule = NULL;  

            return 0;  
        }  
    }  
    else if(type == UdpType)  
    {  
        // 表明查询的是 UDP 信息   
        PMIB_UDPEXTABLE pUdpExTable = NULL;  
        PFNAllocateAndGetUdpExTableFromStack pAllocateAndGetUdpExTableFromStack;  
        pAllocateAndGetUdpExTableFromStack =   
            (PFNAllocateAndGetUdpExTableFromStack)GetProcAddress(hModule,"AllocateAndGetUdpExTableFromStack");  
        if (pAllocateAndGetUdpExTableFromStack != NULL)  
        {  
            // 表明为 XP 或者 Server 2003 操作系统   
            if (pAllocateAndGetUdpExTableFromStack(&pUdpExTable, TRUE, GetProcessHeap(), 0, AF_INET) != 0)  
            {  
                if (pUdpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                }  

                FreeLibrary(hModule);  
                hModule = NULL;  

                return 0;  
            }  

            for (UINT i = 0; i < pUdpExTable->dwNumEntries; i++)  
            {  
                // 过滤掉数据,只查询我们需要的进程数据   
                if (dwPort == ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort))  
                {  
                    DWORD dwProcessId = pUdpExTable->table[i].dwProcessId;  
                    if (pUdpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                    }  

                    FreeLibrary(hModule);  
                    hModule = NULL;  

                    return dwProcessId;  
                }  
            }  

            if (pUdpExTable)  
            {  
                HeapFree(GetProcessHeap(), 0, pUdpExTable);  
            }  

            FreeLibrary(hModule);  
            hModule = NULL;  

            return 0;  
        }  
        else  
        {  
            // 表明为 Vista 或者 7 操作系统   
            PFNInternalGetUdpTableWithOwnerPid pInternalGetUdpTableWithOwnerPid;  
            pInternalGetUdpTableWithOwnerPid =   
                (PFNInternalGetUdpTableWithOwnerPid)GetProcAddress(hModule, "InternalGetUdpTableWithOwnerPid");  
            if (pInternalGetUdpTableWithOwnerPid != NULL)  
            {  
                if (pInternalGetUdpTableWithOwnerPid(&pUdpExTable, GetProcessHeap(), 1))  
                {  
                    if (pUdpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                    }  

                    FreeLibrary(hModule);  
                    hModule = NULL;  

                    return 0;  
                }  

                for (UINT i = 0; i < pUdpExTable->dwNumEntries; i++)  
                {  
                    // 过滤掉数据,只查询我们需要的进程数据   
                    if (dwPort == ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort))  
                    {  
                        DWORD dwProcessId = pUdpExTable->table[i].dwProcessId;  
                        if (pUdpExTable)  
                        {  
                            HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                        }  

                        FreeLibrary(hModule);  
                        hModule = NULL;  

                        return dwProcessId;  
                    }  
                }  
            }  

            if (pUdpExTable)  
            {  
                HeapFree(GetProcessHeap(), 0, pUdpExTable);  
            }  

            FreeLibrary(hModule);  
            hModule = NULL;  

            return 0;  
        }  
    }  
    else  
    {  
        FreeLibrary(hModule);  
        hModule = NULL;  

        return -1;  
    }  
}  


//===========================================================================================//   
//Name: DWORD GetAllPortByProcessId()                                                        //   
//Descripion: 根据进程ID得到该进程所打开的所有的端口号,并且在 dwAllPort 数组中返回所有端口号//   
//            其中 dwMaxLen 为数组的长度,函数的返回值为进程所打开的端口的数目               //   
//            (支持 XP,Server 2003,Vista,Win7)                                            //   
//===========================================================================================//   
extern "C" __declspec(dllexport) DWORD __stdcall GetAllPortByProcessId(TcpOrUdp type, DWORD dwProcessId, DWORD * dwAllPort, DWORD dwMaxLen)  
{  
    DWORD dwPortCount = 0;  
    HMODULE hModule = LoadLibraryW(L"iphlpapi.dll");  
    if (hModule == NULL)  
    {  
        return dwPortCount;  
    }  

    if(type == TcpType)  
    {  
        // 表明查询的是 UDP 信息   
        PFNAllocateAndGetTcpExTableFromStack pAllocateAndGetTcpExTableFromStack;  
        pAllocateAndGetTcpExTableFromStack = (PFNAllocateAndGetTcpExTableFromStack)GetProcAddress(hModule, "AllocateAndGetTcpExTableFromStack");  
        if (pAllocateAndGetTcpExTableFromStack != NULL)  
        {  
            // 表明为 XP 或者 Server 2003 操作系统   
            PMIB_TCPEXTABLE pTcpExTable = NULL;  
            if (pAllocateAndGetTcpExTableFromStack(&pTcpExTable, TRUE, GetProcessHeap(), 0, AF_INET) != 0)  
            {  
                if (pTcpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                }  

                FreeLibrary(hModule);  
                hModule = NULL;  

                return dwPortCount;  
            }  

            for (UINT i = 0; i < pTcpExTable->dwNumEntries; i++)  
            {  
                // 过滤掉数据,只获取我们要查询的进程的 Port 信息   
                if(dwProcessId == pTcpExTable->table[i].dwProcessId)  
                {  
                    if(dwPortCount < dwMaxLen)  
                    {  
                        dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort);  
                        dwPortCount++;  
                    }  
                }  
            }  

            if (pTcpExTable)  
            {  
                HeapFree(GetProcessHeap(), 0, pTcpExTable);  
            }  

            FreeLibrary(hModule);  
            hModule = NULL;  

            return dwPortCount;  
        }  
        else  
        {  
            // 表明为 Vista 或者 7 操作系统   
            PMIB_TCPEXTABLE_VISTA pTcpExTable = NULL;  
            PFNInternalGetTcpTable2 pInternalGetTcpTable2 = (PFNInternalGetTcpTable2)GetProcAddress(hModule, "InternalGetTcpTable2");  
            if (pInternalGetTcpTable2 == NULL)  
            {  
                if (pTcpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                }  

                FreeLibrary(hModule);  
                hModule = NULL;  

                return dwPortCount;  
            }  

            if (pInternalGetTcpTable2(&pTcpExTable, GetProcessHeap(), 1))  
            {  
                if (pTcpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                }  

                FreeLibrary(hModule);  
                hModule = NULL;  

                return dwPortCount;  
            }  

            for (UINT i = 0;i < pTcpExTable->dwNumEntries; i++)  
            {  
                // 过滤掉数据,只获取我们要查询的进程的 TCP Port 信息   
                if(dwProcessId == pTcpExTable->table[i].dwProcessId)  
                {  
                    if(dwPortCount < dwMaxLen)  
                    {  
                        dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort);  
                        dwPortCount++;  
                    }  
                }  
            }  

            if (pTcpExTable)  
            {  
                HeapFree(GetProcessHeap(), 0, pTcpExTable);  
            }  

            FreeLibrary(hModule);  
            hModule = NULL;  

            return dwPortCount;  
        }  
    }  
    else if(type == UdpType)  
    {  
        // 表明查询的是 UDP 信息   
        PMIB_UDPEXTABLE pUdpExTable = NULL;  
        PFNAllocateAndGetUdpExTableFromStack pAllocateAndGetUdpExTableFromStack;  
        pAllocateAndGetUdpExTableFromStack = (PFNAllocateAndGetUdpExTableFromStack)GetProcAddress(hModule,"AllocateAndGetUdpExTableFromStack");  
        if (pAllocateAndGetUdpExTableFromStack != NULL)  
        {  
            // 表明为 XP 或者 Server 2003 操作系统   
            if (pAllocateAndGetUdpExTableFromStack(&pUdpExTable, TRUE, GetProcessHeap(), 0, AF_INET) != 0)  
            {  
                if (pUdpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                }  

                FreeLibrary(hModule);  
                hModule = NULL;  

                return dwPortCount;  
            }  

            for (UINT i = 0; i < pUdpExTable->dwNumEntries; i++)  
            {  
                // 过滤掉数据,只获取我们要查询的进程的 UDP Port信息   
                if(dwProcessId == pUdpExTable->table[i].dwProcessId)  
                {  
                    if(dwPortCount < dwMaxLen)  
                    {  
                        dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort);  
                        dwPortCount++;  
                    }  
                }  
            }  

            if (pUdpExTable)  
            {  
                HeapFree(GetProcessHeap(), 0, pUdpExTable);  
            }  

            FreeLibrary(hModule);  
            hModule = NULL;  

            return dwPortCount;  
        }  
        else  
        {  
            // 表明为 Vista 或者 7 操作系统   
            PFNInternalGetUdpTableWithOwnerPid pInternalGetUdpTableWithOwnerPid;  
            pInternalGetUdpTableWithOwnerPid = (PFNInternalGetUdpTableWithOwnerPid)GetProcAddress(hModule, "InternalGetUdpTableWithOwnerPid");  
            if (pInternalGetUdpTableWithOwnerPid != NULL)  
            {  
                if (pInternalGetUdpTableWithOwnerPid(&pUdpExTable, GetProcessHeap(), 1))  
                {  
                    if (pUdpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                    }  

                    FreeLibrary(hModule);  
                    hModule = NULL;  

                    return dwPortCount;  
                }  

                for (UINT i = 0; i < pUdpExTable->dwNumEntries; i++)  
                {  
                    // 过滤掉数据,只获取我们要查询的进程的 UDP Port信息   
                    if(dwProcessId == pUdpExTable->table[i].dwProcessId)  
                    {  
                        if(dwPortCount < dwMaxLen)  
                        {  
                            dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort);  
                            dwPortCount++;  
                        }  
                    }  
                }  
            }  

            if (pUdpExTable)  
            {  
                HeapFree(GetProcessHeap(), 0, pUdpExTable);  
            }  

            FreeLibrary(hModule);  
            hModule = NULL;  

            return dwPortCount;  
        }  
    }  
    else  
    {  
        FreeLibrary(hModule);  
        hModule = NULL;  

        return dwPortCount;  
    }  
}  
View Code

如果要在.Net平台下使用,将其编译成DLL,使用PInvoke得到DLL导出函数就可以了。

C#测试代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ProcessorPortDllTest
{
    public enum TcpOrUdp
    {
        TcpType,
        UdpType
    };

    public class ProcessPortHelper
    {
        [DllImport("ProcessorPort.dll",CallingConvention = CallingConvention.StdCall)]
        public extern static uint GetProcessIdByPort(TcpOrUdp type, uint dwPort);

        [DllImport("ProcessorPort.dll",CallingConvention = CallingConvention.StdCall)]
        public extern static uint GetAllPortByProcessId(TcpOrUdp type, uint dwProcessId, uint[] dwAllPort, uint dwMaxLen);
    }

    class Program
    {
        static void Main(string[] args)
        {
            uint port = 1025;
            uint processorId = ProcessPortHelper.GetProcessIdByPort(TcpOrUdp.TcpType, port);
            Console.WriteLine("Port {0} is using by processor {1}",port,processorId);

            uint processorId1 = 1072;

            uint[] TcpPorts = new uint[100];
            uint count = ProcessPortHelper.GetAllPortByProcessId(TcpOrUdp.TcpType, processorId1, TcpPorts, (uint)TcpPorts.Length);
            Console.WriteLine("Processor {0} is using TCP port: ", processorId1);
            for (uint i = 0; i < count; ++i)
            {
                Console.WriteLine(TcpPorts[i]);
            }

            uint[] UdpPorts = new uint[100];
            uint count1 = ProcessPortHelper.GetAllPortByProcessId(TcpOrUdp.UdpType, processorId1, UdpPorts, (uint)UdpPorts.Length);
            Console.WriteLine("Processor {0} is using UDP port: ", processorId1);
            for (uint i = 0; i < count1; ++i)
            {
                Console.WriteLine(UdpPorts[i]);
            }

Console.ReadKey(); } } }

 

获得进程监听TCP/UDP端口号的DLL:ProcessorPort.rar

 

posted @ 2013-11-02 21:05  阿凡卢  阅读(14479)  评论(0编辑  收藏  举报