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

C# Socket绑定出现Address already in use异常的问题求助

问题:Socket绑定0.0.0.0时抛出Address already in use异常(SocketException 98)

我基于.NET 6.0.301开发Socket通信功能,测试时采用本机自收发数据的方式,此前该功能正常运行数周,可正常建立连接、收发数据及关闭连接。但重启路由器后,监听Socket绑定IPAddress.Any(0.0.0.0)端点时抛出SocketException(98),提示“Address already in use”,源代码未做任何修改。

监听Socket用于接收任意IP的连接,使用的是固定未变更的闲置随机端口,相关简化代码如下:

// 基类构造函数中:
IpEndPoint = new IPEndPoint(IPAddress.Any, Port); // 固定未变更的闲置随机端口
// ...

// 派生类构造函数中调用
private async Task ReceiveDataAsync()
{
    using Socket listener = new(IpEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    try
    {
        listener.Bind(IpEndPoint); // 此处抛出异常!!!
        listener.Listen(100);
    }
    catch(Exception e)
    {
        Console.WriteLine(e);
        throw;
    }

    while(true)
    {
        using Socket handler = await listener.AcceptAsync();
        // 接收数据...
    }
}

该方法仅被调用一次,首次执行即抛出异常,调用时间远早于连接尝试时间。另外,接收数据后未调用Shutdown、DisconnectAsync或Close关闭连接,但之前均是客户端发送完数据后执行这些操作。

异常信息:

System.Net.Sockets.SocketException (98): Address already in use
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at ....ReceiveDataAsync() ...

补充:IDE(JetBrains Rider)打开项目但未运行时,执行netstat -ntpl | grep 0.0.0.0输出:

tcp        0      0 0.0.0.0:31415           0.0.0.0:*               LISTEN      
10064/dotnet        
tcp        0      0 127.0.0.1:42103         0.0.0.0:*               LISTEN      
9560/Rider.Backend  
tcp        0      0 127.0.0.1:33747         0.0.0.0:*               LISTEN      
9560/Rider.Backend  
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      
-                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
-

杀死占用端口的进程后,重启应用又会生成新进程占用该端口。


解决方案
  1. 清理残留的.NET进程
    从netstat输出可见,未运行项目时已有dotnet进程占用目标端口,说明之前的应用进程未完全退出。可执行以下命令彻底清理:

    pkill dotnet
    

    操作后重启应用,观察端口占用是否恢复正常。

  2. 添加ReusePort Socket选项
    仅设置ReuseAddress在Linux环境下可能不足以解决端口占用问题,需额外添加ReusePort选项,允许多个进程绑定同一端口(若业务需要):

    listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    // 添加ReusePort选项
    listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReusePort, true);
    

    注意:ReusePort在Windows系统下仅支持Windows 10/Server 2016及以上版本。

  3. 确保Socket连接完全释放
    虽然接收端的handler使用了using语句自动释放资源,但建议在接收完数据后显式调用Shutdown,确保Socket资源彻底释放:

    using Socket handler = await listener.AcceptAsync();
    try
    {
        // 接收数据逻辑...
        handler.Shutdown(SocketShutdown.Both);
    }
    finally
    {
        handler.Close();
    }
    
  4. 排查端口抢占问题
    重启路由器后可能有系统服务或其他应用抢占了目标端口,可更换一个端口测试,或用更精准的命令确认占用情况:

    ss -tulpn | grep 目标端口号
    

    检查是否有非dotnet进程占用端口。

  5. 清理Rider残留进程
    Rider有时会残留调试进程,即使停止运行也不会退出。可在Rider中点击Run -> Stop All,或直接杀死Rider.Backend相关进程后,重新启动项目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 09:35:28