【c#源码】基于TCP通信的客户端断线重连

来源:互联网 发布:js窗口大小改变事件 编辑:程序博客网 时间:2024/06/06 08:43

源码下载

在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版本,代码稍微变化:

public static void ClearDic()        {            lock (globalDictAndDelegateLocker)            {                allConnectionsByIdentifier.Clear();                allConnectionsByEndPoint.Clear();                oldNetworkIdentifierToConnectionInfo.Clear();            }        }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();        }           }}客户端代码

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

至此,我们的工作已经完成。

祝大家工作顺利 

 

0 0
原创粉丝点击