基于TCP通信的客户端断线重连 大家帮忙看看这样写法是否可行

Sunny5816 2015-02-28 01:46:13
前面发表了一篇博客,看到有朋友说看到使用static会使得event 爆炸,我也不是很理解,希望知道的朋友帮忙看一下,谢谢

原博文如下:

源码下载
在CS程序中,断线重连应该是一个常见的功能。

此处的断线重连主要指的是服务器端因为某种故障,服务器端程序或者系统进行了重新启动,客户端能够自动探测到服务器端掉线,并尝试重新进行连接

本程序基于来自英国的开源c#通信框架的networkcomms(2.3.1版本)

先看一下效果

初始状态:
当服务器端程序关闭后,客户端会自动探测到,并在客户端显示相关信息



然后,我们设定为每隔5秒重连一次,可以自定义设置重连的次数,比如说重连50次,如果还没有重连成功,则放弃重连


然后我们重新启动服务器端,客户端会显示重连成功.

具体步骤如下:

需要修改几处NetworkComms2.3.1通信框架中的代码

第一步:修改ConnectionInfo类的NoteConnectionShutdown方法

该方法原来是:
internal void NoteConnectionShutdown()
{
lock (internalLocker)
ConnectionState = ConnectionState.Shutdown;
}


修改后为:
private bool reconnectFlag = false;
/// <summary>
/// 是否为重连接模式
/// </summary>
public bool ReconnectFlag
{
get { return reconnectFlag; }
set { reconnectFlag = value; }
}

/// <summary>
/// Note this connection as shutdown
/// </summary>
internal void NoteConnectionShutdown()
{
lock (internalLocker)
ConnectionState = ConnectionState.Shutdown;
//添加以下代码 初始状态为False 触发连接状态改变事件
if (reconnectFlag == false)
{
StateChanged.Raise(this, new StringEventArgs("连接出现异常"));
}

}

//添加状态改变事件

public event EventHandler<StringEventArgs> StateChanged;


第二步:在NetworkComms库类中添加相关的代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using NetworkCommsDotNet.Tools;

namespace NetworkCommsDotNet
{
public static class Extensions
{
public static void Raise<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
{
if (handler != null)
handler(sender, args);
}

}

public class StringEventArgs : EventArgs
{
public StringEventArgs(string text)
{
Text = text;
}
public string Text { get; set; }

}

}

namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
public sealed class ExtensionAttribute : Attribute { }
}

相关代码


第三步:在NetworkComms静态类中添加如下方法:
public static void ClearDic()
{
lock (globalDictAndDelegateLocker)
{
allConnectionsById.Clear();

allConnectionsByEndPoint.Clear();

oldNetworkIdentifierToConnectionInfo.Clear();
}
}


如果您使用的是V3版本,代码稍微变化:
如果您使用的是V3版本,代码稍微变化:


客户端代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using NetworkCommsDotNet;
using DPSBase;
using System.Net;
using System.Threading;

namespace AppClient
{
public partial class Form1 : Form
{
//连接信息类
public ConnectionInfo connnectionInfo = null;

//连接类
Connection connection;


public Form1()
{
InitializeComponent();

}

//在窗体上显示新信息
void Form_ConnectionStatusNotify(object sender, StringEventArgs e)
{
if (this.InvokeRequired)
{

this.Invoke(new EventHandler<StringEventArgs>(this.Form_ConnectionStatusNotify), sender, e);
}
else
{

lblLink.Text = e.Text;
lblLink.ForeColor = Color.Blue;
}
}

private bool ServerNotifyClose = false;

public event EventHandler<StringEventArgs> ConnectionStatusNotify;

void connnectionInfo_StateChanged(object sender, StringEventArgs e)
{
//如果不是服务器通知关闭,则自动重连,如果是服务器通知关闭,则不作处理
//本Demo中没有使用ServerNotifyClose
if (ServerNotifyClose == false)
{
//更新连接信息类 设置为重连模式
connnectionInfo.ReconnectFlag = true;

ConnectionStatusNotify.Raise(this, new StringEventArgs("可能由于服务器的故障,与服务器端的连接已断开"));

int num = 0;
int retryCount = 30;
int retrySpanInMSecs = 5000;


do
{
try
{
NetworkComms.ClearDic();

connection = TCPConnection.GetConnection(connnectionInfo);


ConnectionStatusNotify.Raise(this, new StringEventArgs("重连成功"));

connnectionInfo.ReconnectFlag = false;

break;
}
catch (Exception ex)
{
num++;
if (num < retryCount)
{

ConnectionStatusNotify.Raise(this, new StringEventArgs("正在进行第" + num + "次重连"));
Thread.Sleep(retrySpanInMSecs);
}
}
}
while (num < retryCount);

}
}


private void button1_Click(object sender, EventArgs e)
{

connnectionInfo = new ConnectionInfo(txtIP.Text, int.Parse(txtPort.Text));

//如果不成功,会弹出异常信息
connection = TCPConnection.GetConnection(connnectionInfo);

button1.Enabled = false;
button1.Text = "连接成功";

//订阅连接信息类中的连接状态改变事件
connnectionInfo.StateChanged += new EventHandler<StringEventArgs>(connnectionInfo_StateChanged);
this.ConnectionStatusNotify += new EventHandler<StringEventArgs>(Form_ConnectionStatusNotify);
}

//获取水果相关信息
private void button2_Click(object sender, EventArgs e)
{
if (listBox1.SelectedIndex > -1)
{
string resMsg = connection.SendReceiveObject<string>("ReqFruitEngName", "ResFruitEngName", 5000, listBox1.Text);

MessageBox.Show("您选择的水果的英文名称是:" + resMsg);

}
else
{
MessageBox.Show("请选择一项");
}
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{

this.Dispose();
}


}
}

客户端代码


服务器端无需额外的设置。

至此,我们的工作已经完成。
...全文
371 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
程序员鼓励师 2015-03-07
  • 打赏
  • 举报
回复
Justin-Liu 2015-03-06
  • 打赏
  • 举报
回复
路过支持一下~
Sunny5816 2015-03-05
  • 打赏
  • 举报
回复
没有朋友支持一下?
SomethingJack 2015-02-28
  • 打赏
  • 举报
回复
关注一下 顶一下 这个网络断线重连 也是我最近关注的一个问题

110,502

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧