TCP自动重连

网上模板:

    public class Socket_wrapper
    {
        public static Socket theSocket = null;
        private static string remoteHost = "192.168.1.14";
        private static int remotePort = 6666;

        private static String SockErrorStr = null;
        private static ManualResetEvent TimeoutObject = new ManualResetEvent(false);
        private static Boolean IsconnectSuccess = false; //异步连接情况,由异步连接回调函数置位
        private static object lockObj_IsConnectSuccess = new object();

        /// 设置心跳
        ///
        private static void SetXinTiao()
        {
            //byte[] inValue = new byte[] { 1, 0, 0, 0, 0x20, 0x4e, 0, 0, 0xd0, 0x07, 0, 0 };// 首次探测时间20 秒, 间隔侦测时间2 秒
            byte[] inValue = new byte[] { 1, 0, 0, 0, 0x88, 0x13, 0, 0, 0xd0, 0x07, 0, 0 };// 首次探测时间5 秒, 间隔侦测时间2 秒
            theSocket.IOControl(IOControlCode.KeepAliveValues, inValue, null);
        }

        /// 创建套接字+异步连接函数
        ///
        ///
        private static bool socket_create_connect()
        {
            IPAddress ipAddress = IPAddress.Parse(remoteHost);
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, remotePort);
            theSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            theSocket.SendTimeout = 1000;

            SetXinTiao();//设置心跳参数  

            #region 异步连接代码

            TimeoutObject.Reset(); //复位timeout事件
            try
            {
                theSocket.BeginConnect(remoteEP, connectedCallback, theSocket);
            }
            catch (Exception err)
            {
                SockErrorStr = err.ToString();
                return false;
            }
            if (TimeoutObject.WaitOne(10000, false))//直到timeout,或者TimeoutObject.set()
            {
                if (IsconnectSuccess)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                SockErrorStr = "Time Out";
                return false;
            }
            #endregion
        }

        /// 异步连接回调函数
        ///
        ///
        static void connectedCallback(IAsyncResult iar)
        {
            #region <remarks>
            /// 1、置位IsconnectSuccess
            #endregion </remarks>

            lock (lockObj_IsConnectSuccess)
            {
                Socket client = (Socket)iar.AsyncState;
                try
                {
                    client.EndConnect(iar);
                    IsconnectSuccess = true;
                    //StartKeepAlive(); //开始KeppAlive检测
                }
                catch (Exception e)
                {
                    //Console.WriteLine(e.ToString());
                    SockErrorStr = e.ToString();
                    IsconnectSuccess = false;
                }
                finally
                {
                    TimeoutObject.Set();
                }
            }
        } 

        /// 同步receive函数
        ///
        ///
        ///
        public string socket_receive(byte[] readBuffer)
        {
            while (true)
            {
                try
                {
                    if (theSocket == null)
                    {
                        if (!socket_create_connect())
                        {
                            Thread.Sleep(1000);
                            continue;
                        }
                    }
                    else if (!theSocket.Connected)
                    {
                        if (!IsSocketConnected())
                            if (!Reconnect())
                            {
                                Thread.Sleep(1000);
                                continue;
                            }
                    }

                    int bytesRec = theSocket.Receive(readBuffer);

                    if (bytesRec == 0)
                    {
                        //warning 0 bytes received
                        if (!Reconnect())
                        {
                            Thread.Sleep(1000);
                            continue;
                        }
                    }
                    return Encoding.ASCII.GetString(readBuffer, 0, bytesRec);
                }
                catch (SocketException se)
                {
                    //print se.ErrorCode
                    throw;
                }
            }
        }

        /// 同步send函数
        ///
        ///
        ///
        public bool socket_send(string sendMessage)
        {
            if (checkSocketState())
            {
                return SendData(sendMessage);
            }
            return false;
        }

        /// 同步发送
        ///
        ///
        ///
        public static bool SendData(string dataStr)
        {
            bool result = false;
            if (dataStr == null || dataStr.Length < 0)
                return result;
            try
            {
                byte[] cmd = Encoding.Default.GetBytes(dataStr);
                int n = theSocket.Send(cmd);
                if (n < 1)
                    result = false;
            }
            catch (Exception ee)
            {
                SockErrorStr = ee.ToString();
                result = false;
            }
            return result;
        }

        /// 当socket.connected为false时,进一步确定下当前连接状态
        ///
        ///
        private bool IsSocketConnected()
        {
            #region remarks
            /********************************************************************************************
             * 当Socket.Conneted为false时, 如果您需要确定连接的当前状态,请进行非阻塞、零字节的 Send 调用。
             * 如果该调用成功返回或引发 WAEWOULDBLOCK 错误代码 (10035),则该套接字仍然处于连接状态;
             * 否则,该套接字不再处于连接状态。
             * Depending on http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.connected.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2
            ********************************************************************************************/
            #endregion

            #region 过程
            // This is how you can determine whether a socket is still connected.
            bool connectState = true;
            bool blockingState = theSocket.Blocking;
            try
            {
                byte[] tmp = new byte[1];

                theSocket.Blocking = false;
                theSocket.Send(tmp, 0, 0);
                //Console.WriteLine("Connected!");
                connectState = true; //若Send错误会跳去执行catch体,而不会执行其try体里其之后的代码
            }
            catch (SocketException e)
            {
                // 10035 == WSAEWOULDBLOCK
                if (e.NativeErrorCode.Equals(10035))
                {
                    //Console.WriteLine("Still Connected, but the Send would block");
                    connectState = true;
                }

                else
                {
                    //Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
                    connectState = false;
                }
            }
            finally
            {
                theSocket.Blocking = blockingState;
            }

            //Console.WriteLine("Connected: {0}", client.Connected);
            return connectState;
            #endregion
        }

        /// 断线重连函数
        ///
        ///
        private static bool Reconnect()
        {
            //关闭socket
            theSocket.Shutdown(SocketShutdown.Both);

            theSocket.Disconnect(true);
            IsconnectSuccess = false;

            theSocket.Close();

            //创建socket
            return socket_create_connect();
        }

        /// 检测socket的状态
        ///
        ///
        public static bool checkSocketState()
        {
            try
            {
                if (theSocket == null)
                {
                    return socket_create_connect();
                }
                else if (IsconnectSuccess)
                {
                    return true;
                }
                else//已创建套接字,但未connected
                {
                    #region 异步连接代码

                    TimeoutObject.Reset(); //复位timeout事件
                    try
                    {
                        IPAddress ipAddress = IPAddress.Parse(remoteHost);
                        IPEndPoint remoteEP = new IPEndPoint(ipAddress, remotePort);
                        theSocket.BeginConnect(remoteEP, connectedCallback, theSocket);

                        SetXinTiao();//设置心跳参数
                    }
                    catch (Exception err)
                    {
                        SockErrorStr = err.ToString();
                        return false;
                    }
                    if (TimeoutObject.WaitOne(2000, false))//直到timeout,或者TimeoutObject.set()
                    {
                        if (IsconnectSuccess)
                        {
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    }
                    else
                    {
                        SockErrorStr = "Time Out";
                        return false;
                    }

                    #endregion
                }

            }
            catch (SocketException se)
            {
                SockErrorStr = se.ToString();
                return false;
            }
        }
    }

个人简化改进:

 public void SocketCreateConnect()
        {
            try
            {
                tcpClient = new TcpClient(localEP);
                tcpClient.BeginConnect(remoteEP.Address, remoteEP.Port, ConnectedCallback, tcpClient);
            }
            catch
            { }

        }

        /// 异步连接回调函数
        ///
        ///
        private void ConnectedCallback(IAsyncResult iar)
        {
            #region <remarks>
            /// 1、置位IsconnectSuccess
            #endregion </remarks>

            lock (lockObj_IsConnectSuccess)
            {
                TcpClient tcpClient = (TcpClient)iar.AsyncState;
                try
                {
                    tcpClient.EndConnect(iar);
                    //IsconnectSuccess = true;
                    Receive_Radar29();
                }
                catch (Exception e)
                {
                    //IsconnectSuccess = false;
                    Thread.Sleep(10000);
                    tcpClient.BeginConnect(remoteEP.Address, remoteEP.Port, ConnectedCallback, tcpClient);
                }
            }
        }

        /// 当socket.connected为false时,进一步确定下当前连接状态
        ///
        ///
        private bool IsSocketConnected()
        {
            #region remarks
            /********************************************************************************************
             * 当Socket.Conneted为false时, 如果您需要确定连接的当前状态,请进行非阻塞、零字节的 Send 调用。
             * 如果该调用成功返回或引发 WAEWOULDBLOCK 错误代码 (10035),则该套接字仍然处于连接状态;
             * 否则,该套接字不再处于连接状态。
             * Depending on http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.connected.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2
            ********************************************************************************************/
            #endregion

            #region 过程
            // This is how you can determine whether a socket is still connected.
            bool connectState = true;
            bool blockingState = tcpClient.Client.Blocking;
            try
            {
                byte[] tmp = new byte[1];

                tcpClient.Client.Blocking = false;
                tcpClient.Client.Send(tmp, 0, 0);
                //Console.WriteLine("Connected!");
                connectState = true; //若Send错误会跳去执行catch体,而不会执行其try体里其之后的代码
            }
            catch (SocketException e)
            {
                // 10035 == WSAEWOULDBLOCK
                if (e.NativeErrorCode.Equals(10035))
                {
                    //Console.WriteLine("Still Connected, but the Send would block");
                    connectState = true;
                }

                else
                {
                    //Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
                    connectState = false;
                }
            }
            finally
            {
                tcpClient.Client.Blocking = blockingState;
            }

            //Console.WriteLine("Connected: {0}", client.Connected);
            return connectState;
            #endregion
        }

        /// 断线重连函数
        ///
        ///
        private void Reconnect()
        {
            //IsconnectSuccess = false;

            tcpClient.Close();
            streamToServer.Close();

            //创建socket
            SocketCreateConnect();
        }

        private void Receive_Radar29()
        {
            buffer = new byte[BufferSize];
            while (true)
            {
                try
                {
                    if (!tcpClient.Client.Connected)
                    {
                        if (!IsSocketConnected())
                        {
                            Reconnect();
                            return;
                        }
                    }

                    streamToServer = tcpClient.GetStream();
                    int count = streamToServer.Read(buffer, 0, BufferSize);
                    if (count == 0)
                    {
                        Reconnect();
                        return;
                    }
                    temp_buffer = new byte[count];
                    Array.Copy(buffer, 0, temp_buffer, 0, temp_buffer.Length);
                    Array.Clear(buffer, 0, buffer.Length);
                    List<byte[]> protocolList = requestHandler.GetActualProtocolByte(temp_buffer.ToList());
                    foreach (var item in protocolList)
                    {
                        Task.Factory.StartNew(ProcessProtocol, item);
                        //ProcessProtocol(item);
                    }
                }
                catch
                {
                    //if (streamToServer != null)
                    //{
                    //    streamToServer.Close();
                    //}
                    //tcpClient.Close();
                    //break;
                    continue;
                }
            }
        }

原文地址:https://www.cnblogs.com/liuslayer/p/9438398.html

时间: 2024-10-16 15:55:09

TCP自动重连的相关文章

python之tcp自动重连

操作系统: CentOS 6.9_x64 python语言版本: 2.7.13 问题描述 现有一个tcp客户端程序,需定期从服务器取数据,但由于种种原因(网络不稳定等)需要自动重连. 测试服务器示例代码: https://github.com/mike-zhang/pyExamples/blob/master/socketRelate/tcpServer1_multithread.py 解决方案 ''' tcp client with reconnect E-Mail : [email prot

解读dbcp自动重连那些事(转)

本文转自:http://agapple.iteye.com/blog/791943 可以后另一篇做对比:http://agapple.iteye.com/blog/772507 同样的内容,不同的描述方式,不一样的效果. Hi all : 最近在做 offerdetail 优化时,替换了数据库驱动,从 c3p0 0.9.1 -> dbcp 1.4 , 顺便研究了下 dbcp 的自动重连的一套机制,也做一下分享,大家周知一下. 数据库链接 常见的问题: 1. 数据库意外重启后,原先的数据库连接池能

Netty 自动重连

from: http://www.dozer.cc/2015/05/netty-auto-reconnect.html 自动重连 用 Netty 写 Client 和 Server 的时候必须要去处理自动重连. Server 端启动时的错误,要去不断重试. Client 端不仅要处理启动时的错误,还要处理中途断开连接. Server 端的处理 和常规的代码相比,Server 端只要处理一个地方即可: public final class TcpServer { private volatile

解读dbcp自动重连那些事---转载

http://agapple.iteye.com/blog/791943 可以后另一篇做对比:http://agapple.iteye.com/blog/772507 同样的内容,不同的描述方式,不一样的效果. Hi all : 最近在做 offerdetail 优化时,替换了数据库驱动,从 c3p0 0.9.1 -> dbcp 1.4 , 顺便研究了下 dbcp 的自动重连的一套机制,也做一下分享,大家周知一下. 数据库链接 常见的问题: 1. 数据库意外重启后,原先的数据库连接池能自动废弃老

WordPress实现上传文件自动重命名

打开"wp-admin/includes/file.php"文件的第365行代码,原文是这样的: 可以看出,文件并没有自动重命名,因此我们只需要把圈起来的哪一行进行修改即可实现上传文件时自动重命名的效果,具体修改成下面这种形式: $new_file = $uploads['path'] . "/".date("YmdHis").floor(microtime()*1000).".".$ext; 这段代码的意思是以当前时间的字符

WordPress 中文图片 上传 自动重命名

WordPress 中文图片 上传 自动重命名 由于国人很少有在上传图片前将图片名重命名为英语的,所以自动重命名对于WP来说尤为重要,特别是LINUX的不支持中文名的. WordPress上传多媒体的代码都存放于\wp-admin\includes\里面的file.php,打开这个文件,filename=wpuniquefilename(uploads['path'], file[′name′],unique_filename_callback );// Move the file to the

Spring+Rmi中的客户端自动重连配置

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"   "http://www.springframework.org/dtd/spring-beans.dtd"><beans>    <bean id="xxx" class="org.s

提取论文标题并自动重命名pdf文件

在我们确定一个研究课题之后,我们总是会先下载一堆相关的paper,看看这个领域现在已经做到一个什么地步,也看看别人是怎么做的,后面自己写paper的时候可以参考参考.当我们把相关的文章都下载到一个文件夹之后,有一个问题,一般我们从IEEE或是ACM相关站点下载的PDF文件的文件名不是相应文章的标题.我们希望文件名尽量能够反映文件的主要内容,文章的标题显然是最能概括文张内容的.昨天上午,一个小时的时间就花在把下载下来的文件重命名上了.因为太费时间,想自己写个简单的小程序来完成这个工作.上网一找,嗬

WordPress 实现附件上传自动重命名但不改变附件标题

WordPress 上传媒体文件时,默认会保持文件名不变.如果上传文件名中包含中文字符,则会造成部分浏览器显示的文件 URL 疑似乱码甚至无法访问.网上流行较广的是通过注册  wp_handle_upload_prefilter 过滤器实现,但是该方案在重命名文件的同时也会将附件的标题修改,造成数据丢失.本篇文章将介绍一种既能自动重命名文件名且不改变附件标题的方法. 将以下代码添加到所使用主题的functions.php 文件中最后一个?>的前面即可. 1 function wp_coderbu