C# + Socket断线重连 整理
Socket 连接异常之"由于目标机器积极拒绝,无法连接(System.Net.Sockets.SocketException:Connection refused)"
1.如果是采用TCP/udp协议进行连接,检查windows防火墙是否开放相应SocketTCP/udp端口;
简单的检测方法是关闭windows防火墙后再试;
2.检查防火墙软件是否开放相应SocketTCP/udp端口;
简单的检测方法是关闭防火墙软件后再试;
3.如果服务器端和客户端均在本机上运行,则将相应的 serverIP="127.0.0.1",serveraddress="127.0.0.1";
服务器端侦听:
listener = new TcpListener(IPAddress.Parse(serverIP), listenport);
listener.Start();
客户端与服务器建立连接:
clientsocket = new TcpClient(serveraddress, serverport);
4.如果服务器运行在局域网或广域网内,则将相应的
serverIP,serveraddress设为本机所在局域网或广域网上的IP;
注意 serverport==listenport;
System.Net.Sockets.SocketException: 向一个无法连接的网络尝试了一个套接字操作(System.Net.Sockets.SocketException:Network is unreachable)
IPAddress ipserver = IPAddress.Parse("192.x.x.x");
//IPAddress ipserver = IPAddress.Parse("127.0.0.1");这个没问题
socket.Connect(ipserver, 4000);
------解决方案--------------------
"192.x.x.x" 不是一个有效的地址
127.0.0.1是回送地址,协议立即返回不进行任何网络传输
代码没有任何问题,你需要检查你所要连接的主机IP地址和端口号,用telnet ip port测试看看是不是能连上远程主机
一、网上常用方法
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 == 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
- {
- 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;
- else
- return 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.ErrorCode
- throw;
- }
- }
- ///
- /// 同步send函数
- ///
- ///
- ///
- public bool socket_send(string sendMessage)
- {
- if (checkSocketState())
- {
- return SendData(sendMessage);
- }
- return false;
- }
- ///
- /// 断线重连函数
- ///
- ///
- private static bool Reconnect()
- {
- //关闭socket
- theSocket.Shutdown(SocketShutdown.Both);
- theSocket.Disconnect(true);
- IsconnectSuccess = false;
- theSocket.Close();
- //创建socket
- return 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 == 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
- }
- ///
- /// 另一种判断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;
- else
- return 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-退出,不再执行BeginReceive
- return;
- }
- }
- }
- //此处buffer似乎要清空--待实现 zq
- theSocket.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;
- }
- }
- }
三、源码下载 Sock_Wrapper.cs_免费高速下载|百度网盘-分享无限制
C# + Socket断线重连 整理相关推荐
- asyncio.Protocol socket 断线重连
asyncio.Protocol socket 断线重连 原文:https://www.jianshu.com/p/f5bc755d3d8a 场景 使用asyncio.Protocol进行异步连接时, ...
- Socket断线重连
一.网上常用方法 1.当Socket.Conneted == false时,调用如下函数进行判断 ////// 当socket.connected为false时,进一步确定下当前连接状态 /// // ...
- C# Socket客户端采用双线程断网重连断线重连)
C# Socket客户端采用双线程断网重连断线重连 2021年07月15日 13:38:18更新 C# Socket服务端 双线程断网重连断线重连 C# Socket客户端采用双线程断网重连断线重连 ...
- Android Socket连接(模拟心跳包,断线重连,发送数据等)
首页 博客 学院 下载 GitChat TinyMind 论坛 问答 商城 VIP 活动 招聘 ITeye CSTO 写博客 发Chat 喻志强的博客 耐心 细心 用心 传播正能量 RSS订阅 原 A ...
- android 心跳 简书,Android Socket保持心跳长连接,断线重连
昨天三点钟才睡觉的,现在胸口感觉闷闷的,兄弟们,我是不是要GG了?如果我G了,求大佬们给我烧个女朋友, ss.gif 1.在使用Socket连接客户端和服务器端的时候,如果服务端断开了连接,我们客户端 ...
- Socket网络编程tcp聊天案例(心跳包,多线程,断线重连机制)
实现一个聊天的案例,使用多线程和心跳包.当服务器断开的时候,客户端会自动尝试重新连接,当服务器开启的时候,客户端会自动连接 Server服务器类 package Demo3_Chat;import c ...
- Android 通过 NSD 服务 Netty(断线重连、心跳、黏包处理) 实现两个 Android 系统端的长连接通讯
引言 近期需求,通过手机App端取号机(含叫号通知功能),实时连接 另一台 Android 广告机用于播放当前被叫到的号数. 这里有两种Android 机 一台「基于Sunmi版的可出小票的Andro ...
- 浅谈IM软件客户端的断线重连、心跳和长在线
----------------------------------------------------欢迎查看IM软件业务知识<专栏>-------------------------- ...
- 面试官问:服务的心跳机制与断线重连,Netty底层是怎么实现的?懵了
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 心跳机制 何为心跳 所谓心跳, 即在 TCP 长连接中, ...
最新文章
- 基于 HTML5 WebGL 的 3D 棉花加工监控系统
- Linux:网络基础配置
- repadmin查看域控之间的复制状态
- 2021巨量引擎连锁经营行业洞察报告
- ISO8583报文协议详解
- php默认字体是什么,在word中系统默认的中文字体和字号是什么,word默认字体
- C#导入Excel报错问题3。
- 微服务面试题 - Spring Cloud
- Android Studio在运行时显示Please Select Android SDK的解决方法
- 质造未来,首届腾讯WeTest技术交流开放日成功举办
- Port-A-Thon
- AGI (Analytical Graphics Inc.)
- 计算机网络管理工作记录,网络管理如何查看电脑开机、关机记录
- Statis Acticity 改为Fragment
- 《蔡康永情商课——为自己活一次》
- 人脸识别 年龄 matlab,基于年龄变化的人脸识别
- 华为路由交换——三层交换机与路由器之间链路实现交互
- 四个模型与指标体系的建立
- 【ISAR成像定标方法(1)—转台目标的RD成像算法MATLAB仿真】
- IMX6Q 启动过程详细分析
热门文章
- MySQL主从配置与Mycat读写分离
- C语言中将二维数组作为函数参数来传递
- gin框架长连接_[Golang] Gin框架学习笔记
- Android打开浏览器网址
- Win10不能直接拖文件进行打开解决 办法
- docker中mysql的备份与恢复
- 用FCN来分类皮肤病(应用类型的项目)
- t420i升级固态硬盘提升_雷克沙移动固态硬盘体验:给自己办公最大升级,数据读写速度飙升...
- 我们学校有一个计算机室英文,[转载]25 (四年级下册)第一单元 我们的学校--英汉对照...
- MySQL日期与时间差