C# Socket客户端采用双线程断网重连断线重连

  • 2021年07月15日 13:38:18更新
  • C# Socket服务端 双线程断网重连断线重连
  • C# Socket客户端采用双线程断网重连断线重连
  • 四、原代码地址


一、C#里面,我们可以使用 Thread.Start方法来启动一个线程,当我们想停止执行的线程时可以使用Thread.Abort方法来强制停止正在执行的线程,但是刚开始笔者使用单线程起动与停止线程却没有做到理想的结果却给笔者一头的雾水。刚开始,用Socket类的Connected属性来实现,却发现行不通,connected只表示 是在上次 还是 操作时连接到远程主机。如果在这之后[连接的另一方]断开了,它还一直返回true,笔者使用Abort来终止线程得到的结果却是线程状态《ThreadState》被挂起为《Suspend》想进入到《Aborted》状态却永远做不到。在Socket客户端连接服务器有时因为断网或长时间收不到服务器消息就要重新连接服务端,笔者刚开始采用的是单线程连接结果用了所有的办法都达不到理想状态,于是想到了使用双线程连接结果达到了笔者所想要的结果。服务端采用心跳包发送数据。客户端用来检测发过来的数据。如果6秒钟检测不到数据就认为连接断开进行重新连接。效果如下图(一)所示:

Android Socket 短线重连_c#


网络断开重连如图(二)所示

Android Socket 短线重连_Android Socket 短线重连_02

二、双线程部分代码

#region 线程一与线程二起动
        /**********************************************************************************************
* Author:	<杏雨>   
* Create date: <2021年7月2日>
* Description:< 线程一,线程二起动方法 > 
* 一、线程关闭使用Abort方法能在目标线程中抛出一个ThreadAbortException异常从而导致目标线程的终止。不过Abort方法被调用后,目标线程可能并不是马上就终止了。因为只要目标线程正在调用非托管的代码而且还没有返回的话,该线程就不会立即终止。而如果目标线程在调用非托管的代码而且陷入了一个死循环的话,该目标线程就根本不会终止。
* 
* 二、只使用一个线程使用Abort方法关闭线程是关闭不了的,使用的结果是线程状态<ThreadState>将被挂起<Suspend()>永远进入不了  <Aborted>状态这一点作者已经验证。
* 
* 三、本例使用双线程进行切换是结束线程的一个好方法。由于接收方法<ReceiveMsg()>接收服务端发送的消息是一个while循环 如果设置为TRUE将是一个死循环,一个死循环线程是无法退出的,所以在while循环中设置了开关<jumpLoopFlg>如果为FALSE while死循环才能退出,并在循环中设置一个检测jumpLoopFlg真假判断如果为假则退出循环。时钟是判断是否退出循环的唯一 方法 
         **********************************************************************************************/
   private void Thread_1_Start()
     {
         string strEroor = string.Format("服务器连接已断开,正在起动线程(1)重新链接...\r\n");
         AppendToText(strEroor);
         jumpLoopFlg = false;//先关循环
         client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
         thCondition = 1;
         jumpLoopFlg = true;//然后在起动
         ConnectSocket(thCondition, PublicConts.ip, PublicConts.post);
         ThreadTime();
         string ipAdd = client.LocalEndPoint.ToString();
         string remote = client.RemoteEndPoint.ToString();
         string str = string.Format("线程(1)起动SocKet成功:本地地址:{0}服务器地址{1}", ipAdd, remote);
         AppendToText(str);
         Thread.Sleep(1000);

     }
     private void Thread_2_Start()
     {
         string strEroor = string.Format("服务器连接已断开,正在起动线程(2)重新链接...\r\n");
         AppendToText(strEroor);
         jumpLoopFlg = false;
         client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
         thCondition = 2;
         jumpLoopFlg = true;
         ConnectSocket(thCondition, PublicConts.ip, PublicConts.post);
         ThreadTime();
         string ipAdd = client.LocalEndPoint.ToString();
         string remote = client.RemoteEndPoint.ToString();
         string str = string.Format("线程(2)起动SocKet成功:本地地址:{0}服务器地址{1}", ipAdd, remote);
         AppendToText(str);
         Thread.Sleep(1000);
     }
     #endregion

2021年07月15日 13:38:18更新

C# Socket服务端 双线程断网重连断线重连

1、修改了断网判断不准确的BUG
2、修改了运行2-4小时就假死机的现象,本次运行24小时不停机没有发现问题
3、增加了客户端心跳包的检测

C# Socket客户端采用双线程断网重连断线重连

1、修改了断网判断不准确的BUG
2、增加了服务器端故障检测与断网重连
3、增加了对服务器端心跳包的检测
4、服务器端故障检测采用双线程中的一个线程进行检测。以前采用新开一个Socket进行重新连接,连接成功后在删除这个Socket这样会造成服务器端的繁忙删除
5、服务器端与客户端进行了24小时不停机测试现在没有发现问题,以前半小时后或2-4小时就会断线重连主要原因是断网的误判造成。这次增加了对心跳包检测

三、下图是客户端先开,然后在开服务器端的效果图,一般情况下是先开服务器端在开客户端,否则就会出现异常,由于作者对客户端增加了服务器端的错误检测所以在后开服务器也没有什么问题。由于是双线程当一个线程连接出现故障系统会自动切换到另一个线程继续工作。

Android Socket 短线重连_服务器端_03

四、原代码地址

1、 服务端:
2、客户端: