一、网上常用方法
1、当Socket.Conneted == false时,调用如下函数进行判断

////// 当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 = socket.Blocking;try{byte[] tmp = new byte[1];socket.Blocking = false;socket.Send(tmp, 0, 0);//Console.WriteLine("Connected!");connectState = true; //若Send错误会跳去执行catch体,而不会执行其try体里其之后的代码}catch (SocketException e){// 10035 == WSAEWOULDBLOCKif (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{socket.Blocking = blockingState;}//Console.WriteLine("Connected: {0}", client.Connected);return connectState;#endregion
}
2、根据socket.poll判断
点击(此处)折叠或打开
////// 另一种判断connected的方法,但未检测对端网线断开或ungraceful的情况
///
///
///
static bool IsSocketConnected(Socket s)
{#region remarks/* As zendar wrote, it is nice to use the Socket.Poll and Socket.Available, but you need to take into conside                ration * that the socket might not have been initialized in the first place. * This is the last (I believe) piece of information and it is supplied by the Socket.Connected property. * The revised version of the method would looks something like this: * from:http://stackoverflow.com/questions/2661764/how-to-check-if-a-socket-is-connected-disconnected-in-c */#endregion#region 过程return !((s.Poll(1000, SelectMode.SelectRead) && (s.Available == 0)) || !s.Connected);/* The long, but simpler-to-understand version:bool part1 = s.Poll(1000, SelectMode.SelectRead);bool part2 = (s.Available == 0);if ((part1 && part2 ) || !s.Connected)return false;elsereturn true;*/#endregion
}

2、根据socket.poll判断

////// 另一种判断connected的方法,但未检测对端网线断开或ungraceful的情况
///
///
///
static bool IsSocketConnected(Socket s)
{#region remarks/* As zendar wrote, it is nice to use the Socket.Poll and Socket.Available, but you need to take into conside                ration * that the socket might not have been initialized in the first place. * This is the last (I believe) piece of information and it is supplied by the Socket.Connected property. * The revised version of the method would looks something like this: * from:http://stackoverflow.com/questions/2661764/how-to-check-if-a-socket-is-connected-disconnected-in-c */#endregion#region 过程return !((s.Poll(1000, SelectMode.SelectRead) && (s.Available == 0)) || !s.Connected);/* The long, but simpler-to-understand version:bool part1 = s.Poll(1000, SelectMode.SelectRead);bool part2 = (s.Available == 0);if ((part1 && part2 ) || !s.Connected)return false;elsereturn true;*/#endregion
}

总结:–1–此两种方法出处可在函数体中的remark中找到链接
–2–此两种方法适用于对端正常关闭socket下的本地socket状态检测,在非正常关闭如断电、拔网线的情况下不起作用
因为Socket.Conneted存在bug,详见.Net Bugs
二、支持物理断线重连功能的类

    利用BeginReceive + KeepAlive实现物理断线重连,初步测验了一下,正常。(部分代码参考帖子#26及blog在C#中利用keep-alive处理socket网络异常断开)Keep-Alive机制的介绍请看TCP Keepalive HOWTO以此备忘,同时希望能帮助到有需要的同学。
 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;namespace MySocket
{public class Socket_wrapper{//委托private delegate void delSocketDataArrival(byte[] data);static delSocketDataArrival socketDataArrival = socketDataArrivalHandler;private delegate void delSocketDisconnected();static delSocketDisconnected socketDisconnected = socketDisconnectedHandler;public static Socket theSocket = null;private static string remoteHost = "192.168.1.71";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();////// 构造函数/// /// /// public Socket_wrapper(string strIp, int iPort){remoteHost = strIp;remotePort = iPort;}////// 设置心跳/// 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}////// 同步receive函数/// /// /// public string socket_receive(byte[] readBuffer){try{if (theSocket == null){socket_create_connect();}else if (!theSocket.Connected){if (!IsSocketConnected())Reconnect();}int bytesRec = theSocket.Receive(readBuffer);if (bytesRec == 0){//warning 0 bytes received}return Encoding.ASCII.GetString(readBuffer, 0, bytesRec);}catch (SocketException se){//print se.ErrorCodethrow;}}////// 同步send函数/// /// /// public bool socket_send(string sendMessage){if (checkSocketState()){return SendData(sendMessage);}return false;}////// 断线重连函数/// /// private static bool Reconnect(){//关闭sockettheSocket.Shutdown(SocketShutdown.Both);theSocket.Disconnect(true);IsconnectSuccess = false;theSocket.Close();//创建socketreturn socket_create_connect();}////// 当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 == WSAEWOULDBLOCKif (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}////// 另一种判断connected的方法,但未检测对端网线断开或ungraceful的情况/// /// /// public static bool IsSocketConnected(Socket s){#region remarks/* As zendar wrote, it is nice to use the Socket.Poll and Socket.Available, but you need to take into consideration * that the socket might not have been initialized in the first place. * This is the last (I believe) piece of information and it is supplied by the Socket.Connected property. * The revised version of the method would looks something like this: * from:http://stackoverflow.com/questions/2661764/how-to-check-if-a-socket-is-connected-disconnected-in-c */#endregion#region 过程if (s == null)return false;return !((s.Poll(1000, SelectMode.SelectRead) && (s.Available == 0)) || !s.Connected);/* The long, but simpler-to-understand version:bool part1 = s.Poll(1000, SelectMode.SelectRead);bool part2 = (s.Available == 0);if ((part1 && part2 ) || !s.Connected)return false;elsereturn true;*/#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();}}}////// 开始KeepAlive检测函数/// private static void StartKeepAlive(){theSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(OnReceiveCallback), theSocket);}////// BeginReceive回调函数/// static byte[] buffer = new byte[1024];private static void OnReceiveCallback(IAsyncResult ar){try{Socket peerSock = (Socket)ar.AsyncState;int BytesRead = peerSock.EndReceive(ar);if (BytesRead > 0){byte[] tmp = new byte[BytesRead];Array.ConstrainedCopy(buffer, 0, tmp, 0, BytesRead);if (socketDataArrival != null){socketDataArrival(tmp);}}else//对端gracefully关闭一个连接{if (theSocket.Connected)//上次socket的状态{if (socketDisconnected != null){//1-重连socketDisconnected();//2-退出,不再执行BeginReceivereturn;}}}//此处buffer似乎要清空--待实现 zqtheSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(OnReceiveCallback), theSocket);}catch (Exception ex){if (socketDisconnected != null){socketDisconnected(); //Keepalive检测网线断开引发的异常在这里捕获return;}}}////// 异步收到消息处理器/// /// private static void socketDataArrivalHandler(byte[] data){}////// socket由于连接中断(软/硬中断)的后续工作处理器/// private static void socketDisconnectedHandler(){Reconnect();}////// 检测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 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断线重连相关推荐

  1. asyncio.Protocol socket 断线重连

    asyncio.Protocol socket 断线重连 原文:https://www.jianshu.com/p/f5bc755d3d8a 场景 使用asyncio.Protocol进行异步连接时, ...

  2. C# + Socket断线重连 整理

    Socket 连接异常之"由于目标机器积极拒绝,无法连接(System.Net.Sockets.SocketException:Connection refused)" 1.如果是 ...

  3. C# Socket客户端采用双线程断网重连断线重连)

    C# Socket客户端采用双线程断网重连断线重连 2021年07月15日 13:38:18更新 C# Socket服务端 双线程断网重连断线重连 C# Socket客户端采用双线程断网重连断线重连 ...

  4. Android Socket连接(模拟心跳包,断线重连,发送数据等)

    首页 博客 学院 下载 GitChat TinyMind 论坛 问答 商城 VIP 活动 招聘 ITeye CSTO 写博客 发Chat 喻志强的博客 耐心 细心 用心 传播正能量 RSS订阅 原 A ...

  5. android 心跳 简书,Android Socket保持心跳长连接,断线重连

    昨天三点钟才睡觉的,现在胸口感觉闷闷的,兄弟们,我是不是要GG了?如果我G了,求大佬们给我烧个女朋友, ss.gif 1.在使用Socket连接客户端和服务器端的时候,如果服务端断开了连接,我们客户端 ...

  6. Socket网络编程tcp聊天案例(心跳包,多线程,断线重连机制)

    实现一个聊天的案例,使用多线程和心跳包.当服务器断开的时候,客户端会自动尝试重新连接,当服务器开启的时候,客户端会自动连接 Server服务器类 package Demo3_Chat;import c ...

  7. springboot redis 断线重连_Redis复制:部分同步PSYNC详解

    概述 在Redis2.8之前,如果从服务器在主从复制的过程中,出现了断线,重连之后需要全量同步一次主服务器上面的数据,即从服务器发送SYNC命令给主服务器,请求进行全量同步,但是断线重连之后,从服务器 ...

  8. springboot redis 断线重连_Redis的主从复制是如何做的?复制过程中也会产生各种问题?...

    如果Redis的读写请求量很大,那么单个实例很有可能承担不了这么大的请求量,如何提高Redis的性能呢?你也许已经想到了,可以部署多个副本节点,业务采用读写分离的方式,把读请求分担到多个副本节点上,提 ...

  9. netty心跳过程中 发送消息失败_Netty 4.0 实现心跳检测和断线重连

    arg0.pipeline().addLast("ping", new IdleStateHandler(25, 15, 10,TimeUnit.SECONDS)); 这个处理器, ...

最新文章

  1. 目标检测算法终结篇:YOLOv7(非正式版)正式开源
  2. 十一、springboot WebMvcConfigurer与HandlerInterceptorAdapter使用
  3. Java内存分配原理
  4. UI组件之AdapterView及其子类(五)ListView组件和ListActivity
  5. 游标 和 锁的概述
  6. 前端学习(924):client系列
  7. C++获取多维数组维数
  8. bat循环执行带参数_wxappUnpacker的bingo.bat脚本逐行解读
  9. process 类 java_编写可执行jar——java的Process类的使用(二)
  10. mysql数学函数有什么_mysql数学函数有哪些?
  11. Math源码java_从零开始的Java学习记录(26)——Math类及其些许源码
  12. 显示隐藏、淡入淡出、上卷下展的区别
  13. CAN总线分析仪使用及调试方式
  14. oracle alter system kill,ALTER SYSTEM KILL SESSION详解
  15. InstallShield 模块详解
  16. 如何不打开excel文件搜索其中内容---在线绿色工具
  17. 市政管理学(试题及答案)汇总
  18. JS-part12.3-ES6- 箭头函数 / 函数的参数默认值 / 模板字符串 / 点点点运算符 / 解构赋值 / 对象的简写形式
  19. websocket服务器无响应,WebSocket服务器因某些原因无法正常工作(WebSocket server not working for some reasons)...
  20. 黑客攻击第二次,开redis一瞬间

热门文章

  1. wms仓储管理系统有哪些特点?
  2. 矩阵快速幂递推(五行)
  3. Excel VBA –更改工作表后运行宏
  4. c++bind函数使用
  5. 如何解决Web前端安全问题?
  6. JCJC句子改写在线工具上线-202305
  7. YAHFA--ART环境下的Hook框架
  8. 【程序员思维进阶】(8)
  9. python爬取花瓣妹子信息
  10. poj 2244 最短路 和 poj 1874 畅通工程续 dijkstra(迪杰斯特拉)