獲取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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM