TcpTable.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using System;
  2. using System.Buffers.Binary;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. using System.Runtime.InteropServices;
  6. using System.Runtime.Versioning;
  7. namespace FastGithub.ReverseProxy
  8. {
  9. /// <summary>
  10. /// windows iphlpapi
  11. /// </summary>
  12. [SupportedOSPlatform("windows")]
  13. unsafe static class TcpTable
  14. {
  15. private const int ERROR_INSUFFICIENT_BUFFER = 122;
  16. [DllImport("iphlpapi.dll", SetLastError = true)]
  17. private static extern uint GetExtendedTcpTable(void* pTcpTable, ref int pdwSize, bool bOrder, AddressFamily ulAf, TCP_TABLE_CLASS tableClass, uint reserved = 0);
  18. /// <summary>
  19. /// 获取tcp端口的占用进程id
  20. /// </summary>
  21. /// <param name="port"></param>
  22. /// <param name="processId"></param>
  23. /// <returns></returns>
  24. public static bool TryGetOwnerProcessId(int port, out int processId)
  25. {
  26. processId = 0;
  27. var pdwSize = 0;
  28. var result = GetExtendedTcpTable(null, ref pdwSize, false, AddressFamily.InterNetwork, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER);
  29. if (result != ERROR_INSUFFICIENT_BUFFER)
  30. {
  31. return false;
  32. }
  33. var buffer = new byte[pdwSize];
  34. fixed (byte* pTcpTable = &buffer[0])
  35. {
  36. result = GetExtendedTcpTable(pTcpTable, ref pdwSize, false, AddressFamily.InterNetwork, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER);
  37. if (result != 0)
  38. {
  39. return false;
  40. }
  41. var prt = new IntPtr(pTcpTable);
  42. var table = Marshal.PtrToStructure<MIB_TCPTABLE_OWNER_PID>(prt);
  43. prt += sizeof(int);
  44. for (var i = 0; i < table.dwNumEntries; i++)
  45. {
  46. var row = Marshal.PtrToStructure<MIB_TCPROW_OWNER_PID>(prt);
  47. if (row.LocalPort == port)
  48. {
  49. processId = row.ProcessId;
  50. return true;
  51. }
  52. prt += Marshal.SizeOf<MIB_TCPROW_OWNER_PID>();
  53. }
  54. }
  55. return false;
  56. }
  57. private enum TCP_TABLE_CLASS
  58. {
  59. TCP_TABLE_BASIC_LISTENER,
  60. TCP_TABLE_BASIC_CONNECTIONS,
  61. TCP_TABLE_BASIC_ALL,
  62. TCP_TABLE_OWNER_PID_LISTENER,
  63. TCP_TABLE_OWNER_PID_CONNECTIONS,
  64. TCP_TABLE_OWNER_PID_ALL,
  65. TCP_TABLE_OWNER_MODULE_LISTENER,
  66. TCP_TABLE_OWNER_MODULE_CONNECTIONS,
  67. TCP_TABLE_OWNER_MODULE_ALL
  68. }
  69. [StructLayout(LayoutKind.Sequential)]
  70. private struct MIB_TCPTABLE_OWNER_PID
  71. {
  72. public uint dwNumEntries;
  73. }
  74. [StructLayout(LayoutKind.Sequential)]
  75. private struct MIB_TCPROW_OWNER_PID
  76. {
  77. public uint state;
  78. public uint localAddr;
  79. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  80. public byte[] localPort;
  81. public uint remoteAddr;
  82. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  83. public byte[] remotePort;
  84. public int owningPid;
  85. public int ProcessId => owningPid;
  86. public IPAddress LocalAddress => new(localAddr);
  87. public ushort LocalPort => BinaryPrimitives.ReadUInt16BigEndian(this.localPort);
  88. }
  89. }
  90. }