基于TCP通信的客户端断线重连

转载:http://www.cnblogs.com/networkcomms/p/4304362.html

源码下载

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

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

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

先看一下效果

初始状态:

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

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

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

具体步骤如下:

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

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

该方法原来是:

   internal void NoteConnectionShutdown()
        {
            lock (internalLocker)
                ConnectionState = ConnectionState.Shutdown;
        }

View Code

修改后为: 

   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();
        }

    }
}

客户端代码

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

时间: 2024-10-14 22:55:13

基于TCP通信的客户端断线重连的相关文章

java tcp通信-JAVA TCP通信,客户端给服务器发送java对象时报错

问题描述 JAVA TCP通信,客户端给服务器发送java对象时报错 我在做JAVA TCP 编程时,我想实现客户端A与客户端B之间通过服务器C来通信,但是我通过客户端A给服务器发送消息时,我传送的是一个java对象MsgPackage类对象,我通过ObjectOutputStream.writeObject来传送,但是服务器去读取这个对象时报错了,没有能正确读取到客户端发送过来的对象,请各位大神指教一下.错误的消息是这样: java.lang.ClassNotFoundException: c

WCF 客户端断线重连中遇到的问题

问题描述 最近在用WCF做一个项目,现在测试实现断线重连的问题,我直接将网络断开然后再启动,可以实现重连:问题来了:由于WCF服务程序里边有个方法:publicvoidUserAccept(){IUserCallBackcallBack=OperationContext.Current.GetCallbackChannel<IUserCallBack>();stringsessionid=OperationContext.Current.SessionId;OperationContext.C

关于socket tcp 断线重连

这个问题困扰过我几次,都没有来得及研究,今天研究一下. 首先写一个最简易的socket tcp程序,连接成功后再关闭服务器然后再用客户端各种操作看是什么情况 测试表明 (1)客户端已经连接,当服务端关闭程序时,客户端调用send函数发送失败,WSAGetLastError() 返回10054(远程主机强迫关闭了一个现有的连接)  (2)客户端已经连接,当客户端关闭程序时,服务端调用recv函数接收失败,WSAGetLastError() 返回10054(远程主机强迫关闭了一个现有的连接) ,这时

C# tcp 通信时,KeepALive 时自动断开 问题 急,急,急求大侠帮助

问题描述 在.net平台下使用c#进行tcp通信,客户端发送命令服务器端收到后执行命令,服务器端执行时间大概几个小时,然后返回给客户端结果.在此期间客户端使用阻塞的方式Read方法读取,为了防止TCP在长链接时断开,我启用了c#tcp中的KeepAlive机制,每三分钟发一次心跳包.但是过了一个多小时read()方法触发异常,"无法从传输连接中读取数据:你的主机中的软件终止了一个已建立的连接.",我用wireshark查看,发现触发异常时候心跳包还能正常接收.不知道什么原因导致read

Java基于TCP方式的二进制文件传输_java

一个基于Java Socket协议之上文件传输的完整示例,基于TCP通信完成. 除了基于TCP的二进制文件传输,还演示了JAVA Swing的一些编程技巧,Demo程序 实现主要功能有以下几点: 1.基于Java Socket的二进制文件传输(包括图片,二进制文件,各种文档work,PDF) 2.SwingWorker集合JProgressBar显示实时传输/接受完成的百分比 3.其它一些Swing多线程编程技巧 首先来看一下整个Dome的Class之间的关系图: 下面按照上图来详细解释各个类的

用C#实现基于TCP协议的网络通讯

网络 TCP协议是一个基本的网络协议,基本上所有的网络服务都是基于TCP协议的,如HTTP,FTP等等,所以要了解网络编程就必须了解基于TCP协议的编程.然而TCP协议是一个庞杂的体系,要彻底的弄清楚它的实现不是一天两天的功夫,所幸的是在.net framework环境下,我们不必要去追究TCP协议底层的实现,一样可以很方便的编写出基于TCP协议进行网络通讯的程序. 要进行基于TCP协议的网络通讯,首先必须建立同远程主机的连接,连接地址通常包括两部分--主机名和端口,如www.yesky.c

用C#实现基于用C#实现基于TCP协议的网络通讯

网络 TCP协议是一个基本的网络协议,基本上所有的网络服务都是基于TCP协议的,如HTTP,FTP等等,所以要了解网络编程就必须了解基于TCP协议的编程.然而TCP协议是一个庞杂的体系,要彻底的弄清楚它的实现不是一天两天的功夫,所幸的是在.net framework环境下,我们不必要去追究TCP协议底层的实现,一样可以很方便的编写出基于TCP协议进行网络通讯的程序. 要进行基于TCP协议的网络通讯,首先必须建立同远程主机的连接,连接地址通常包括两部分--主机名和端口,如www.yesky.c

艾伟_转载:用C#实现基于TCP协议的网络通讯

TCP协议是一个基本的网络协议,基本上所有的网络服务都是基于TCP协议的,如HTTP,FTP等等,所以要了解网络编程就必须了解基于TCP协议的编程.然而TCP协议是一个庞杂的体系,要彻底的弄清楚它的实现不是一天两天的功夫,所幸的是在.net framework环境下,我们不必要去追究TCP协议底层的实现,一样可以很方便的编写出基于TCP协议进行网络通讯的程序.  要进行基于TCP协议的网络通讯,首先必须建立同远程主机的连接,连接地址通常包括两部分--主机名和端口,如www.yesky.com:8

C#基于TCP协议的服务器端和客户端通信编程的基础教程_C#教程

运行在TCP之上常见的网络应用协议有比如HTTP.FTP.SMTP.POP3.IMAP. TCP是TCP/IP体系中最重要的传输协议,它提供全双工和可靠交付的服务,是大多数应用协议工作的基础. TCP是一种面向连接(连接导向)的,可靠的,基于字节流的传输层通信协议. TCP的工作过程 建立连接 传输数据 连接的终止 TCP的主要特点1.TCP是面向连接的协议 2.是端到端的通信.每个TCP连接只能有两个端点,而且只能一对一通信,不能点对多的 的直接通信 3.高可靠性 4.全双工方式传输 5.数据