TCP自动重连
Posted liuslayer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; } } }
以上是关于TCP自动重连的主要内容,如果未能解决你的问题,请参考以下文章
stm32+lwip作为MCU与tcp/ip协议栈,其为一般TCP客户端,具有断开重连机制,并作为HTTP的服务端,求代码!