1. 程式人生 > >TCP自動重連

TCP自動重連

list save Coding locale [] ext eat blocking one

網上模板:

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

TCP自動重連