Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

急救!远程主机强迫关闭了一个现有的连接。 #768

Open
loveyeguo opened this issue Dec 16, 2024 · 20 comments
Open

急救!远程主机强迫关闭了一个现有的连接。 #768

loveyeguo opened this issue Dec 16, 2024 · 20 comments

Comments

@loveyeguo
Copy link

此代码:

   private async Task KeepAccept(Socket listenSocket)
   {
       while (!_cancellationTokenSource.IsCancellationRequested)
       {
           try
           {
               var client = await listenSocket.AcceptAsync().ConfigureAwait(false);
               OnNewClientAccept(client);
           }
           catch (Exception e)
           {
               if (e is ObjectDisposedException || e is NullReferenceException)
                   break;
               
               if (e is SocketException se)
               {
                   var errorCode = se.ErrorCode;

                   //The listen socket was closed
                   if (errorCode == 125 || errorCode == 89 || errorCode == 995 || errorCode == 10004 || errorCode == 10038)
                   {
                       break;
                   }
               }
               
               _logger.LogError(e, $"Listener[{this.ToString()}] failed to do AcceptAsync");
               continue;
           }
       }

       _stopTaskCompletionSource.TrySetResult(true);
   } 

目前客户端有200多个,运行几分钟后,程序一直报错:
Listener[Ip=Any, Port=1799, Security=None, Path=, BackLog=0, NoDelay=False] failed to do AcceptAsync远程主机强迫关闭了一个现有的连接。
此时测试程序端口仍然能够正常连接并传输数据,只是一直报错而已。但运行5-6小时后,新的客户端将无法再次连接。
我使用老版1.6版本,同样监听此端口,报错也有,但是运行一天以后,新的客户端依然可以正常连接。
请问如何解决? 谢谢大佬!

@wj8400684
Copy link
Contributor

会不会是你电脑问题

@loveyeguo
Copy link
Author

不会

@loveyeguo
Copy link
Author

我已经测试了好几遍了,确定是supersocket程序本身bug。

@wj8400684
Copy link
Contributor

建议写个最小demo复现

@loveyeguo
Copy link
Author

直接用源码侦听就复现了,没有写任何逻辑代码,就侦听两个端口。运行5-6个小时,新的客户端无法再次连接。现在我暂时修复了这个bug : 修改代码如下:

 public bool Start()
        {
            var options = Options;

            try
            {
                if (options.Security != SslProtocols.None && options.CertificateOptions != null)
                {
                    options.CertificateOptions.EnsureCertificate();
                }

                var listenEndpoint = options.GetListenEndPoint();
                var listenSocket = _listenSocket = new Socket(listenEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
                listenSocket.ReceiveTimeout = 10000; // 设置为10秒
                listenSocket.SendTimeout = 10000; // 设置为10秒
                listenSocket.LingerState = new LingerOption(false, 0);

                if (options.NoDelay)
                    listenSocket.NoDelay = true;
                
                listenSocket.Bind(listenEndpoint);
                listenSocket.Listen(options.BackLog);

                IsRunning = true;

                _cancellationTokenSource = new CancellationTokenSource();

                KeepAccept(listenSocket).DoNotAwait();
                return true;
            }
            catch (Exception e)
            {
                _logger.LogError(e, $"The listener[{this.ToString()}] failed to start.");
                return false;
            }
        }

主要就是要在原有代码上增加如下三行:

listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
                listenSocket.ReceiveTimeout = 10000; // 设置为10秒
                listenSocket.SendTimeout = 10000; // 设置为10秒

@loveyeguo
Copy link
Author

原有bug复现大致方法: 让大量tcp客户端不断连接然后断开,tcp服务端在运行几个小时后无法再次连接。

@wj8400684
Copy link
Contributor

那这跟supersocket没啥关系呀 应该是你端口耗尽了

@loveyeguo
Copy link
Author

不是啊,诶,你没完全看我写的。 我都说这么详细了。同一台服务器,用1.6版本,没有问题。用最新版本,出现问题。 目前加了那三行代码,暂时没有出现问题。 麻烦完整看一遍我的描述!

@wj8400684
Copy link
Contributor

解决就行

@loveyeguo
Copy link
Author

我这只是临时解决办法,实际情况错误一直在报,我也不懂啥时候就崩溃了,请问你也是联合开发作者吗? 有空可以关注下这个问题!

@chucklu
Copy link
Contributor

chucklu commented Dec 18, 2024

Please provide the source code of the demo, including both client and server code, and push to your own git repository(maybe you can create a new git repository under your GitHub account)

@loveyeguo
Copy link
Author

模拟不了客户端,客户端是rtu采集模块,200多个,我不清楚客户端做了什么操作,就会引起服务器的上述错误。

@loveyeguo
Copy link
Author

总而言之,只要引起服务端上诉代码报错: 远程主机强迫关闭现有连接,其他服务端代码不要任何逻辑,只负责侦听端口。即可重现bug

@wj8400684
Copy link
Contributor

写个简易demo复现

@fangqifan
Copy link

我也是同样的现象 和你一摸一样

@fangqifan
Copy link

我不清楚是否和windows系统版本或者framework版本有关
我的socket服务器之前运行在windows server 2012和.net framework 4.6.1环境中 一直良好运行
但最近迁移至windows server 2022和.net framework 4.8 和你出现了一样的问题
不同的在于我使用的Supersocket版本为1.6.6.1

@fangqifan
Copy link

我的程序连接了大概20台设备 设备通过移动网络连接服务器 有几台设备地处偏远 信号不稳定 会出现断连 然后自动重连的情况
运行大概20个小时不到就会出现上述情况

@kerryjiang
Copy link
Owner

我怀疑在你的场景下,发生了一下错误,然后listener就不再继续监听了。

//The listen socket was closed
if (errorCode == 125 || errorCode == 89 || errorCode == 995 || errorCode == 10004 || errorCode == 10038)
{
break;
}

@kerryjiang
Copy link
Owner

kerryjiang commented Dec 27, 2024

@loveyeguo 出现这种情况的时候进程是不是挂掉了?

我增加了log,建议从myget上拿最新代码重现这个问题,通过log再来找到导致这个问题的原因。

@loveyeguo
Copy link
Author

@loveyeguo 出现这种情况的时候进程是不是挂掉了?

我增加了log,建议从myget上拿最新代码重现这个问题,通过log再来找到导致这个问题的原因。

不是,并没有进入break,我已经打了日志,程序还是在监听的,而且运行十几个小时后,程序仍然在运行,但是已经无法建立新的连接,而旧连接还有残余2-3个存在。 你看下我前面的记录,已经修改了这个bug。虽然一直报错,但是目前运行一周多了,没有出现无法建立新连接的情况。解决办法就是增加下面代码:

listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
                listenSocket.ReceiveTimeout = 10000; // 设置为10秒
                listenSocket.SendTimeout = 10000; // 设置为10秒

但为什么这么加上就可以了,我自己也没有完全明白。大佬有空可以查查。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants