190 lines
5.9 KiB
C#
190 lines
5.9 KiB
C#
|
|
using Ayay.SerilogLogs;
|
|||
|
|
using Serilog;
|
|||
|
|
using System.Diagnostics;
|
|||
|
|
using System.Net;
|
|||
|
|
using System.Net.NetworkInformation;
|
|||
|
|
using System.Text.RegularExpressions;
|
|||
|
|
|
|||
|
|
namespace SHH.MjpegPlayer
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 网口占用检测
|
|||
|
|
/// </summary>
|
|||
|
|
public static class NetPortExtension
|
|||
|
|
{
|
|||
|
|
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
|
|||
|
|
|
|||
|
|
#region IsServerPort
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 是否端口
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="value"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static bool IsServerPort(this int value)
|
|||
|
|
{
|
|||
|
|
if (value > 0 && value < 65535)
|
|||
|
|
return true;
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region IsPortOccupied
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 端口占用检测
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="port"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 查询端口占用进程 Pid
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="port"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 查询端口占用进程 Pid
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="port"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 端口占用检测并杀掉进程
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="port"></param>
|
|||
|
|
/// <returns>返回占用端口清理结果</returns>
|
|||
|
|
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
|
|||
|
|
}
|
|||
|
|
}
|