LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

[点晴永久免费OA]C#实现netstat的功能获取所有连接到本机的外部IP地址及端口

admin
2022年11月17日 10:5 本文热度 2024

核心思想是调用 WinAPI 中的 GetExtendedTcpTable 方法来获取所有活动的 TCP 连接的信息,包括进程ID等等,主要实现如下:

TcpConnectionTableHelper.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
 
namespace TcpConnectionMonitor
{
 public class TcpConnectionTableHelper
 {
 [DllImport("Ws2_32.dll")]
 static extern ushort ntohs(ushort netshort);
 
 [DllImport("iphlpapi.dll", SetLastError = true)]
 static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwOutBufLen, bool sort, int ipVersion, TCP_TABLE_TYPE tblClass, int reserved);
 
 [StructLayout(LayoutKind.Sequential)]
 public struct MIB_TCPROW_OWNER_PID
 {
 public uint state;
 public uint localAddr;
 public byte localPort1;
 public byte localPort2;
 public byte localPort3;
 public byte localPort4;
 public uint remoteAddr;
 public byte remotePort1;
 public byte remotePort2;
 public byte remotePort3;
 public byte remotePort4;
 public int owningPid;
 
 public ushort LocalPort
 {
 get
 {
 return BitConverter.ToUInt16(new byte[2] { localPort2, localPort1 }, 0);
 }
 }
 
 public ushort RemotePort
 {
 get
 {
 return BitConverter.ToUInt16(new byte[2] { remotePort2, remotePort1 }, 0);
 }
 }
 }
 
 [StructLayout(LayoutKind.Sequential)]
 public struct MIB_TCPTABLE_OWNER_PID
 {
 public uint dwNumEntries;
 MIB_TCPROW_OWNER_PID table;
 }
 
 public static string GetIpAddress(long ipAddrs)
 {
 try
 {
 System.Net.IPAddress ipAddress = new System.Net.IPAddress(ipAddrs);
 return ipAddress.ToString();
 }
 catch { return ipAddrs.ToString(); }
 
 }
 
 public static ushort GetTcpPort(int tcpPort)
 {
 return ntohs((ushort)tcpPort);
 }
 
 public static MIB_TCPROW_OWNER_PID[] GetAllTcpConnections()
 {
 MIB_TCPROW_OWNER_PID[] tcpConnectionRows;
 int AF_INET = 2; // IPv4
 int buffSize = 0;
 
 // use WinAPI GetExtendedTcpTable to query all active tcp connection information
 uint ret = GetExtendedTcpTable(IntPtr.Zero, ref buffSize, true, AF_INET, TCP_TABLE_TYPE.TCP_TABLE_OWNER_PID_ALL, 0);
 if (ret != 0 && ret != 122) // 122 means insufficient buffer size
 {
 throw new Exception("Error occurred when trying to query tcp table, return code: " + ret);
 }
 IntPtr buffTable = Marshal.AllocHGlobal(buffSize);
 
 try
 {
 ret = GetExtendedTcpTable(buffTable, ref buffSize, true, AF_INET, TCP_TABLE_TYPE.TCP_TABLE_OWNER_PID_ALL, 0);
 if (ret != 0)
 {
 throw new Exception("Error occurred when trying to query tcp table, return code: " + ret);
 }
 
 // get the number of entries in the table
 MIB_TCPTABLE_OWNER_PID table = (MIB_TCPTABLE_OWNER_PID)Marshal.PtrToStructure(buffTable, typeof(MIB_TCPTABLE_OWNER_PID));
 IntPtr rowPtr = (IntPtr)((long)buffTable + Marshal.SizeOf(table.dwNumEntries));
 tcpConnectionRows = new MIB_TCPROW_OWNER_PID[table.dwNumEntries];
 
 for (int i = 0; i < table.dwNumEntries; i++)
 {
 MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal.PtrToStructure(rowPtr, typeof(MIB_TCPROW_OWNER_PID));
 tcpConnectionRows[i] = tcpRow;
 rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow));
 }
 }
 finally
 {
 // free memory
 Marshal.FreeHGlobal(buffTable);
 }
 return tcpConnectionRows;
 }
 }
}
 
public enum TCP_TABLE_TYPE : int
{
 TCP_TABLE_BASIC_LISTENER,
 TCP_TABLE_BASIC_CONNECTIONS,
 TCP_TABLE_BASIC_ALL,
 TCP_TABLE_OWNER_PID_LISTENER,
 TCP_TABLE_OWNER_PID_CONNECTIONS,
 TCP_TABLE_OWNER_PID_ALL,
 TCP_TABLE_OWNER_MODULE_LISTENER,
 TCP_TABLE_OWNER_MODULE_CONNECTIONS,
 TCP_TABLE_OWNER_MODULE_ALL
}
 
public enum TCP_CONNECTION_STATE : int
{
 CLOSED = 1,
 LISTENING,
 SYN_SENT,
 SYN_RCVD,
 ESTABLISHED,
 FIN_WAIT_1,
 FIN_WAIT_2,
 CLOSE_WAIT,
 CLOSING,
 LAST_ACK,
 TIME_WAIT,
 delete_TCP
};


Program.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
 
namespace TcpConnectionMonitor
{
 class Program
 {
 static void Main(string[] args)
 {
 MonitorTcpConnections();
 }
 
 static void MonitorTcpConnections()
 {
 Console.WriteLine("Proto Local Address Foreign Address State PID");
 List<String> rows = new List<string>();
 while (true)
 {
 int windowTop = Console.WindowTop; //in order to keep console scroll bar stay
 TcpConnectionTableHelper.MIB_TCPROW_OWNER_PID[] tcpProgressInfoTable = TcpConnectionTableHelper.GetAllTcpConnections();
 int tableRowCount = tcpProgressInfoTable.Length;
 for (int i = 0; i < tableRowCount; i++)
 {
 TcpConnectionTableHelper.MIB_TCPROW_OWNER_PID row = tcpProgressInfoTable[i];
 string source = string.Format("{0}:{1}", TcpConnectionTableHelper.GetIpAddress(row.localAddr), row.LocalPort);
 string dest = string.Format("{0}:{1}", TcpConnectionTableHelper.GetIpAddress(row.remoteAddr), row.RemotePort);
 string outputRow = string.Format("{0, -7}{1, -23}{2, -23}{3, -16}{4}", "TCP", source, dest, (TCP_CONNECTION_STATE)row.state, row.owningPid);
 if (rows.Count < i + 1)
 {
 Console.SetCursorPosition(0, i + 1);
 Console.WriteLine("{0, -80}", outputRow);
 rows.Add(outputRow);
 }
 else if (rows[i] != outputRow)
 {
 rows[i] = outputRow;
 Console.SetCursorPosition(0, i + 1);
 Console.WriteLine("{0, -80}", outputRow);
 }
 }
 if (rows.Count > tableRowCount)
 {
 int linesToBeCleared = rows.Count - tableRowCount;
 rows.RemoveRange(tableRowCount, linesToBeCleared);
 for (int i = 0; i < linesToBeCleared + 1; i++)
 {
 Console.WriteLine("{0, -80}", " ");
 }
 }
 Console.SetWindowPosition(0, windowTop); //in order to keep console scroll bar stay
 Thread.Sleep(100);
 }
 }
 }
}

实现的效果是每 100ms 获取一次活跃 TCP 连接的状态,也就是说每秒大概会刷新10次,为了避免由于刷新频率过快导致闪烁的问题,通过调用 Console.SetCursorPosition 来对变化的数据进行部分刷新,同时为了避免滚动条存在时,Console 指针引起滚动条自动滚动到最后一行,使用 SetWindowPosition 来固定滚动条的位置。

输出结果举例:



该文章在 2022/11/17 10:05:16 编辑过
关键字查询
相关文章
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved