using Ayay.SerilogLogs; using Serilog; using System.Diagnostics; using System.Net; using System.Net.NetworkInformation; using System.Text.RegularExpressions; namespace SHH.MjpegPlayer { /// /// 网口占用检测 /// public static class NetPortExtension { private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); #region IsServerPort /// /// 是否端口 /// /// /// public static bool IsServerPort(this int value) { if (value > 0 && value < 65535) return true; return false; } #endregion #region IsPortOccupied /// /// 端口占用检测 /// /// /// public static bool IsPortOccupied(this int port) { var ipProperties = IPGlobalProperties.GetIPGlobalProperties(); IPEndPoint[] activeListeners = ipProperties.GetActiveTcpListeners(); foreach (var endPoint in activeListeners) { if (endPoint.Port == port) return true; // 端口被占用 } return false; // 端口可用 } #endregion #region GetProcessIdByPort /// /// 查询端口占用进程 Pid /// /// /// public static int GetProcessIdByPort(this int port) { try { using (Process proc = new Process()) { proc.StartInfo.FileName = "cmd.exe"; proc.StartInfo.Arguments = $"/c netstat -ano | findstr :{port}"; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.CreateNoWindow = true; proc.Start(); string output = proc.StandardOutput.ReadToEnd(); proc.WaitForExit(); // 解析输出(示例:TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 1234) Match match = Regex.Match(output, @":\d+\s+.*?LISTENING\s+(\d+)"); if (match.Success && int.TryParse(match.Groups[1].Value, out int pid)) return pid; } return 0; } catch (Exception ex) { _sysLog.Warning("查询端口占用进程出错", ex.Message, ex.StackTrace); return 0; } } #endregion #region GetProcessIdByPort /// /// 查询端口占用进程 Pid /// /// /// public static string GetProcessNameIdByPort(this int port) { try { using (Process proc = new Process()) { proc.StartInfo.FileName = "cmd.exe"; proc.StartInfo.Arguments = $"/c netstat -ano | findstr :{port}"; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.CreateNoWindow = true; proc.Start(); string output = proc.StandardOutput.ReadToEnd(); proc.WaitForExit(); // 解析输出(示例:TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 1234) Match match = Regex.Match(output, @":\d+\s+.*?LISTENING\s+(\d+)"); if (match.Success && int.TryParse(match.Groups[1].Value, out int pid)) { using (Process process = Process.GetProcessById(pid)) return process.ProcessName; } } return string.Empty; } catch (Exception ex) { _sysLog.Warning($"查询端口占用进程出错, 错误信息:{ex.Message} {ex.StackTrace}"); return string.Empty; } } #endregion #region PortOccupiedProc /// /// 端口占用检测并杀掉进程 /// /// /// 返回占用端口清理结果 public static bool PortOccupiedProc(this int port) { if (port.IsPortOccupied()) { _sysLog.Warning("服务器端口被占用, Port: {port}"); // 等待 5 秒 for (var i = 0; i < 10; i++) Thread.Sleep(500); // 查找占用端口的进程 var pid = port.GetProcessIdByPort(); if (pid != 0) { // 获取进程名 string procName = pid.GetProcessName(); // 找到占用端口的进程 _sysLog.Warning($"找到占用端口进程 Pid: {pid} 进程名:{procName}, 5 秒后即将尝试杀掉占用端口的进程."); // 等待 5 秒 for (var i = 0; i < 10; i++) Thread.Sleep(500); // 杀掉指定进程 if (!pid.KillProcessByPid(procName)) { // 退出应用 return false; } // 等待 2 秒 Thread.Sleep(2000); return true; } return false; } return true; } #endregion } }