|
@@ -0,0 +1,94 @@
|
|
|
+using System;
|
|
|
+using System.Buffers.Binary;
|
|
|
+using System.Net;
|
|
|
+using System.Net.Sockets;
|
|
|
+using System.Runtime.InteropServices;
|
|
|
+using System.Runtime.Versioning;
|
|
|
+
|
|
|
+namespace FastGithub.Dns
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// windows iphlpapi
|
|
|
+ /// </summary>
|
|
|
+ [SupportedOSPlatform("windows")]
|
|
|
+ unsafe static class UdpTable
|
|
|
+ {
|
|
|
+ private const int ERROR_INSUFFICIENT_BUFFER = 122;
|
|
|
+
|
|
|
+ [DllImport("iphlpapi.dll", SetLastError = true)]
|
|
|
+ private static extern uint GetExtendedUdpTable(void* pUdpTable, ref int pdwSize, bool bOrder, AddressFamily ulAf, UDP_TABLE_CLASS tableClass, uint reserved = 0);
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取udp端口的占用进程id
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="port"></param>
|
|
|
+ /// <param name="processId"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static bool TryGetOwnerProcessId(int port, out int processId)
|
|
|
+ {
|
|
|
+ processId = 0;
|
|
|
+ var pdwSize = 0;
|
|
|
+ var result = GetExtendedUdpTable(null, ref pdwSize, false, AddressFamily.InterNetwork, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID);
|
|
|
+ if (result != ERROR_INSUFFICIENT_BUFFER)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ var buffer = new byte[pdwSize];
|
|
|
+ fixed (byte* pUdpTable = &buffer[0])
|
|
|
+ {
|
|
|
+ result = GetExtendedUdpTable(pUdpTable, ref pdwSize, false, AddressFamily.InterNetwork, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID);
|
|
|
+ if (result != 0)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ var table = Marshal.PtrToStructure<MIB_UDPTABLE_OWNER_PID>(new IntPtr(pUdpTable));
|
|
|
+ foreach (var row in table.rows)
|
|
|
+ {
|
|
|
+ if (row.LocalPort == port)
|
|
|
+ {
|
|
|
+ processId = row.ProcessId;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private enum UDP_TABLE_CLASS
|
|
|
+ {
|
|
|
+ UDP_TABLE_BASIC,
|
|
|
+ UDP_TABLE_OWNER_PID,
|
|
|
+ UDP_TABLE_OWNER_MODULE
|
|
|
+ }
|
|
|
+
|
|
|
+ [StructLayout(LayoutKind.Sequential)]
|
|
|
+ private struct MIB_UDPTABLE_OWNER_PID
|
|
|
+ {
|
|
|
+ public uint dwNumEntries;
|
|
|
+
|
|
|
+ [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
|
|
|
+ public MIB_UDPROW_OWNER_PID[] rows;
|
|
|
+ }
|
|
|
+
|
|
|
+ [StructLayout(LayoutKind.Sequential)]
|
|
|
+ private struct MIB_UDPROW_OWNER_PID
|
|
|
+ {
|
|
|
+ public uint localAddr;
|
|
|
+
|
|
|
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
|
|
+ public byte[] localPort;
|
|
|
+
|
|
|
+ public int owningPid;
|
|
|
+
|
|
|
+ public int ProcessId => owningPid;
|
|
|
+
|
|
|
+ public IPAddress LocalAddress => new(localAddr);
|
|
|
+
|
|
|
+ public ushort LocalPort => BinaryPrimitives.ReadUInt16BigEndian(this.localPort);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|