#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* 版权所有 (c) 2026 WenJY 保留所有权利。
* CLR版本:4.0.30319.42000
* 机器名称:Mr.Wen's MacBook Pro
* 命名空间:Sln.IntelliBelt.Socket
* 唯一标识:E4DF9972-3038-4900-A2C1-507F30B63F54
*
* 创建者:WenJY
* 电子邮箱:
* 创建时间:2026-05-27 11:13:35
* 版本:V1.0.0
* 描述:
*
*--------------------------------------------------------------------
* 修改人:
* 时间:
* 修改说明:
*
* 版本:V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Sln.IntelliBelt.Socket;
///
/// 端口信息查询结果
///
public class PortProcessInfo
{
public int Port { get; set; }
public string ProcessName { get; set; }
public int Pid { get; set; }
public string LocalAddress { get; set; }
public string RemoteAddress { get; set; }
public string State { get; set; }
public override string ToString()
{
return $"端口:{Port} | 程序:{ProcessName} | PID:{Pid} | {LocalAddress}->{RemoteAddress} | 状态:{State}";
}
}
public static class PortHelper
{
///
/// 根据端口号获取使用该端口的程序信息
///
/// 端口号
/// 程序信息列表
public static List GetProcessByPort(int port)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
|| RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return GetProcessByPortUnix(port);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return GetProcessByPortWindows(port);
}
throw new PlatformNotSupportedException("不支持当前操作系统");
}
#region Unix (macOS / Linux)
private static List GetProcessByPortUnix(int port)
{
var result = new List();
try
{
var psi = new ProcessStartInfo
{
FileName = "lsof",
Arguments = $"-i :{port} -n -P",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
using var process = Process.Start(psi);
var output = process!.StandardOutput.ReadToEnd();
process.WaitForExit();
var lines = output.Split('\n', StringSplitOptions.RemoveEmptyEntries);
// 跳过表头(第一行)
foreach (var line in lines.Skip(1))
{
var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 9) continue;
var command = parts[0];
var pidStr = parts[1];
var namePart = parts[8]; // 格式: localhost:port->localhost:port 或 *:port
if (!int.TryParse(pidStr, out int pid)) continue;
var info = new PortProcessInfo
{
Port = port,
ProcessName = command,
Pid = pid
};
// 解析地址和状态
ParseUnixConnection(namePart, info);
// 如果有状态标识(如 (ESTABLISHED)),取最后一个括号内的内容
var lastPart = parts[^1];
if (lastPart.StartsWith('(') && lastPart.EndsWith(')'))
{
info.State = lastPart.Trim('(', ')');
}
else
{
info.State = "LISTEN";
}
result.Add(info);
}
}
catch (Exception ex)
{
Console.Error.WriteLine($"执行 lsof 失败: {ex.Message}");
}
return result;
}
private static void ParseUnixConnection(string namePart, PortProcessInfo info)
{
// 格式类似: localhost:6000->localhost:51183 或 *:51183
var arrowIdx = namePart.IndexOf("->");
if (arrowIdx > 0)
{
info.LocalAddress = namePart[..arrowIdx];
info.RemoteAddress = namePart[(arrowIdx + 2)..];
}
else
{
info.LocalAddress = namePart;
info.RemoteAddress = "-";
}
}
#endregion
#region Windows
private static List GetProcessByPortWindows(int port)
{
var result = new List();
try
{
// 1. 用 netstat 找到 PID
var connections = new List<(string local, string remote, string state, int pid)>();
var psi = new ProcessStartInfo
{
FileName = "netstat",
Arguments = "-ano",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
using var process = Process.Start(psi);
var output = process!.StandardOutput.ReadToEnd();
process.WaitForExit();
foreach (var line in output.Split('\n', StringSplitOptions.RemoveEmptyEntries).Skip(4))
{
var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 5) continue;
var localAddr = parts[1]; // 如 0.0.0.0:8080
var remoteAddr = parts[2];
var state = parts.Length == 5 ? "LISTEN" : parts[3];
// 取最后一列作为 PID
var lastPart = parts[^1];
if (!int.TryParse(lastPart, out int pid)) continue;
// 检查是否匹配目标端口
var localPort = localAddr.Split(':').Last();
var remotePort = remoteAddr.Split(':').Last();
if (localPort == port.ToString() || remotePort == port.ToString())
{
connections.Add((localAddr, remoteAddr, state, pid));
}
}
// 2. 用 tasklist 找程序名
var pidNameMap = new Dictionary();
psi = new ProcessStartInfo
{
FileName = "tasklist",
Arguments = "/FO CSV /NH",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
using var process2 = Process.Start(psi);
var tasklistOutput = process2!.StandardOutput.ReadToEnd();
process2.WaitForExit();
foreach (var line in tasklistOutput.Split('\n', StringSplitOptions.RemoveEmptyEntries))
{
var trimmed = line.Trim().Trim('"');
var csvParts = trimmed.Split("\",\"");
if (csvParts.Length >= 2 && int.TryParse(csvParts[1], out int pid))
{
pidNameMap[pid] = csvParts[0];
}
}
// 3. 组装结果
foreach (var (local, remote, state, pid) in connections)
{
var processName = pidNameMap.TryGetValue(pid, out var name) ? name : "(未知)";
result.Add(new PortProcessInfo
{
Port = port,
ProcessName = processName,
Pid = pid,
LocalAddress = local,
RemoteAddress = remote,
State = state
});
}
}
catch (Exception ex)
{
Console.Error.WriteLine($"查询失败: {ex.Message}");
}
return result;
}
#endregion
///
/// 判断端口是否被本地 Intel 程序(Sln.Intel)占用
///
/// 端口号
/// true 表示端口被本地 Sln.Intel 相关进程占用
public static bool IsIntelLocalPort(int port)
{
var list = GetProcessByPort(port);
return list.Any(info =>
// 程序名包含 Sln.Intel(忽略大小写)
info.ProcessName.Contains("Sln.Intel",
StringComparison.OrdinalIgnoreCase) //&& IsLocalAddress(info.RemoteAddress);;
// 且连接双方都在本机(localhost 或 127.0.0.1)
&& IsLocalAddress(info.LocalAddress)
&& IsLocalAddress(info.RemoteAddress));
}
///
/// 判断地址是否为本机地址
///
private static bool IsLocalAddress(string address)
{
if (string.IsNullOrEmpty(address)) return false;
// 支持 localhost、127.0.0.1、*:* 等本机形式
return address.StartsWith("localhost:", StringComparison.OrdinalIgnoreCase)
|| address.StartsWith("127.0.0.1:", StringComparison.OrdinalIgnoreCase)
|| address.StartsWith("*:", StringComparison.OrdinalIgnoreCase)
|| address.StartsWith("[::1]:", StringComparison.OrdinalIgnoreCase)
|| address.StartsWith("0.0.0.0:", StringComparison.OrdinalIgnoreCase);
}
#region 便捷方法
///
/// 获取端口对应的第一个程序名称(最常用)
///
/// 端口号
/// 程序名,无结果时返回 null
public static string? GetProcessNameByPort(int port)
{
var list = GetProcessByPort(port);
return list.FirstOrDefault()?.ProcessName;
}
///
/// 输出端口占用详情到控制台
///
public static void PrintPortInfo(int port)
{
var list = GetProcessByPort(port);
if (list.Count == 0)
{
Console.WriteLine($"端口 {port} 没有被任何程序占用");
return;
}
foreach (var item in list)
{
Console.WriteLine(item);
}
}
#endregion
}