Files
Ayay/SHH.MjpegPlayer/Core/Extensions/NetPortExtension.cs

190 lines
5.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}
}