You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何检测端口是否被占用?等待端口可用方案求助

解决端口等待释放的可行方案

你的代码无效的核心原因:TCP连接关闭后会进入TIME_WAIT状态(系统默认保留一段时间,防止延迟报文干扰新连接),此时端口并未真正释放;另外你的空循环没有休眠,会导致CPU占用过高,且可能因系统状态更新延迟漏检。

以下是几种可行的解决办法:

1. 优化端口检查逻辑,包含TIME_WAIT状态并加入休眠

修改等待方法,同时检查所有TCP连接(包括TIME_WAIT),并在循环中加入短暂休眠避免空转:

public static int WaitForPort(int port)
{
    IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
    TimeSpan checkInterval = TimeSpan.FromMilliseconds(100); // 每100ms检查一次

    while (true)
    {
        // 检查所有使用目标端口的TCP连接(包括TIME_WAIT)及监听中的端口
        bool isPortInUse = ipGlobalProperties.GetActiveTcpConnections()
            .Any(conn => conn.LocalEndPoint.Port == port)
            || ipGlobalProperties.GetActiveTcpListeners()
            .Any(listener => listener.Port == port);

        if (!isPortInUse)
            break;

        Thread.Sleep(checkInterval);
    }

    return port;
}

2. 直接尝试绑定端口直到成功

相比先检查再绑定,直接尝试绑定能避免检查与绑定之间的竞争(比如检查时端口可用,但绑定前被其他进程占用):

public static int WaitForPortAndBind(int port)
{
    const int maxAttempts = 100;
    int attempts = 0;
    TimeSpan retryDelay = TimeSpan.FromMilliseconds(200);

    while (attempts < maxAttempts)
    {
        try
        {
            using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                socket.Bind(new IPEndPoint(IPAddress.Loopback, port));
                return port;
            }
        }
        catch (SocketException ex) when (ex.SocketErrorCode == SocketError.AddressAlreadyInUse)
        {
            attempts++;
            Thread.Sleep(retryDelay);
        }
    }

    throw new InvalidOperationException($"端口 {port} 长时间无法释放");
}

3. 启用端口重用(无需等待释放)

如果测试场景允许,直接设置Socket的ReuseAddress选项,强制重用处于TIME_WAIT状态的端口:

// 服务端Socket设置
var serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
serverSocket.Bind(new IPEndPoint(IPAddress.Loopback, port));

// 客户端若需绑定固定端口,同样设置该选项
var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
clientSocket.Bind(new IPEndPoint(IPAddress.Loopback, localPort));

注意:Windows系统下ReuseAddress允许重用TIME_WAIT端口,但同一时间仅能有一个Socket绑定该端口;若需多进程同时监听同一端口,可使用ReusePort选项(需Win10及以上系统)。

内容的提问来源于stack exchange,提问作者Waifu Slayer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 00:20:21