通讯观察线程是个有意思,又是非常实用的功能。
断线重连具体怎么实现呢,很多人都实现过,那么TouchSocket等几个通讯组件中也包含有,都是可以拿来就用。只是,对于高级用户和特别细节操作要求的,是会自定义特别的超时断线业务规则。
首先要有三个方法, start, stop和Restart
/// <summary>
/// 启动
/// </summary>
public bool Start()
{
try
{
//先执行ping 命令
KeepServer = true;
IPAddress ip = IPAddress.Parse(ComPara.ServerIP);
IPEndPoint ipep = new IPEndPoint(ip, ComPara.Port);
Tcpsocket.Connect(ipep);
processor = new Thread(Communication);
processor.IsBackground = true;
processor.Start();
return true;
}
catch (Exception ex)
{
KeepServer = false; //ex.LogError();
return false;
}
finally
{
this.communicationobserve_timer.Enabled = true;
}
}
/// <summary>
/// 停止服务
/// </summary>
public bool Stop()
{
try
{
IsStop = true;
this.communicationobserve_timer.Enabled = false;
KeepServer = false;
Tcpsocket.Close();
Tcpsocket.Dispose();
if (processor != null )
{
processor.Abort();
//解决线程过多情况,因为线程执行Abort,状态是AbortRequested,还是会存在继续执行
while (processor.ThreadState != ThreadState.Aborted)
{ Thread.Sleep(100); }
LogHelper.WorkAndInfo($"LB600 停止服务 Stop();");
}
return true;
}
catch //(Exception ex)
{ //ex.LogError();
return false;
}
}
/// <summary>
/// 重新启动
/// </summary>
protected bool ReStart()
{
try
{
KeepServer = true; //return Start();
IPAddress ip = IPAddress.Parse(ComPara.ServerIP);
IPEndPoint ipep = new IPEndPoint(ip, ComPara.Port);
Tcpsocket.Connect(ipep); //IP和端口
processor = new Thread(Communication);
processor.IsBackground = true;
processor.Start();
//DelegateState.InvokeDispatchStateEvent($" {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} {this.DeviceCode}号机器人,恢复连接成功!");
//Comm.Speak($" {this.DeviceCode}号机器人,启动重连中");
return true;
}
catch //(Exception ex)
{
KeepServer = false; //ex.LogError();
return false;
}
}
第二,要有Reconnect()方法
/// <summary>
/// 重新创建连接
/// </summary>
public void ReConnect()
{
try
{
if (Init())
{
if (ReStart())
{
LastConnectTime = DateTime.Now; //LastRecTime 在有反馈时才记录
Comm.Speak($"{DeviceCode}号设备,掉线后重连成功!");
}
}
}
catch (Exception ex)
{
LogHelper.Error("尝试连接" + $" 将在3秒后重新尝试连接...", ex);
}
}
最重要的是最后这个通讯的超时监测,这里设置就是重联达到的条件,至于两个超时变量如下面定义:
/// <summary>
/// 通讯状态观察
/// </summary>
private void CommunicationObser(object sender, ElapsedEventArgs e)
{
try
{
communicationobserve_timer.Enabled = false;
//if (Monitor.TryEnter(lockobj, TimeSpan.FromSeconds(1)))
{
//先判断 机器人是否已经掉线
if (LastRecLong > 2) //调试时修改为300, 默认1秒,
{
//如果接受消息时间已经大于1秒,则认为掉线了
if (LastConnectLong > 3) //调试时修改为500, 默认3秒
{
//如果车子掉线且连接时间超过3秒则需要重连
LogHelper.WriteSendAGVMessLog($"重连 {DeviceCode}号"); //调试时暂时注释掉//ReConnect(); 添加了LastRecTime = DateTime.Now;
LastRecTime = DateTime.Now;
Comm.Speak($"{DeviceCode}号,掉线后尝试重连");
ReConnect();
}
}
}
}
catch (Exception ex)
{
LogHelper.Error($"观察线程异常:{ex.Message}", ex);
}
finally
{
communicationobserve_timer.Enabled = true;
}
}
/// <summary>
/// 最后一次重新连接的时间
/// </summary>
public DateTime LastConnectTime { get; set; }
/// <summary>
/// 距最后一次重连接的时长(秒)
/// </summary>
public double LastConnectLong
{
get
{
return (DateTime.Now - LastConnectTime).TotalSeconds;
}
}