Socket正常重连.Tcp);varremoteIpAddress=IPAddress.Parse(ChannelIp);ChannelEndPoint=newIPEndPoint(remoteIpAddress,ChannelPort);ChannelSocket.Connect(ChannelEndPoint);我还有一个计时器设置为每60秒触发一次调用CheckConnectivity,它会尝试将任意字节数组发送到端点以确保连接仍然有效,如果发送失败,它将尝试重新连接。publicboolCheckConnectivity(boolisReconnect){if(ChannelSocket!=null){varblockingState=ChannelSocket.Blocking;尝试{vartmp=newbyte[]{0};ChannelSocket.Blocking=false;ChannelSocket.Send(tmp);}catch(SocketExceptione){try{ReconnectChannel();}catch(Exceptionex){返回假;}}}else{ConnectivityLog.Warn(string.Format("{0}:{1}为null!",ChannelIp,ChannelPort));返回假;}返回真;}privatevoidReconnectChannel(){try{ChannelSocket.Shutdown(SocketShutdown.Both);ChannelSocket.Disconnect(true);ChannelSocket.Close();}catch(Exceptionex){ConnectivityLog.Error(ex);}ChannelSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);varremoteIpAddress=IPAddress.Parse(ChannelIp);ChannelEndPoint=newIPEndPoint(remoteIpAddress,ChannelPort);ChannelSocket.Connect(ChannelEndPoint);线程.睡眠(1000);如果(ChannelSocket.Connected){ConnectivityLog.Info(string.Format("{0}:{1}重新连接!",ChannelIp,ChannelPort));}else{ConnectivityLog.Warn(string.Format("{0}:{1}重新连接失败!",ChannelIp,ChannelPort));那么我将如何测试上面的内容,就是从我的以太网设备上拔下LAN电缆,让我的代码尝试重新连接(这显然会失败)并重新连接回LAN电缆,即使重新连接LAN电缆(能够ping)我的重新连接方法中的ChannelSocket.Connect(ChannelEndPoint)也抛出此错误Noconnectioncouldbebecausethetargetmachineactivelyrefusedit192.168.168.160:4001如果我要重新启动整个应用程序,它将成功连接.我该如何调整我的重新连接方法,这样我就不必重新启动我的应用程序来重新连接回我的以太网设备?如果应用程序关闭TCP/IP端口,协议规定该端口在一定时间内保持TIME_WAIT状态(在Windows机器上默认为24??0秒)。请参阅以下参考资料-http://en.wikipedia.org/wiki/Transmission_Control_Protocolhttp://support.microsoft.com/kb/137984http://www.pctools.com/guides/registry/detail/878/这这对您的场景意味着什么-您不能期望关闭(自愿或不情愿)并在短时间内(甚至几秒钟)重新打开端口。尽管您可能会在Internet上找到一些注册表调整...至少30秒内该端口在Windows上的任何应用程序中都不可用。(同样,默认值为240秒)您的选项-此处有限...来自http://msdn.microsoft.com/en-us/library/4xzx2d41(v=vs.110).aspx的文档-“如果套接字如果您之前已断开连接,无法使用此(Connect)方法恢复连接。请使用其中一种异步BeginConnect方法重新连接。这是底层提供程序的限制。”文档建议必须使用BeginConnect的原因是我上面提到的..它根本不希望能够立即建立连接..所以唯一的选择是在等待建立连接时异步调用在几分钟内,预期并计划失败。基本上,可能不是一个理想的选择。如果漫长的等待和不确定性是不可接受的,您的另一个选择是以某种方式协商客户端和服务器之间的不同端口。(例如,理论上您可以使用无连接UDP来协商您重新建立连接的新TCP端口)。当然,理论上使用UDP进行通信本身并不能保证设计。但大部分时间应该都能正常工作(典型组织中的网络今天并不那么不稳定/不可靠)。主观情景/意见,可能比选项1更好,但工作更多,失败的可能性更小但有限。正如其中一条评论所建议的那样,这是像http和http服务这样的应用层协议的优势所在。如果可以,请使用它们而不是低级套接字。如果可以接受,这是最好的选择。(PS-仅供参考-对于HTTP,操作系统内置了很多特殊处理,包括Windows-例如,有一个专用驱动程序Http.sys,专门用于处理多个应用程序试图侦听同一个端口80等。..这里的细节是另一个话题..关键是,当涉及到HTTP时,已经为你做了很多好的和艰苦的工作)也许你应该切换到一个更高的抽象类,它可以更好地处理所有这些小细节?我将为这些网络连接使用TcpListener和TcpClient类。这类的使用非常简单:客户方:publicvoidGetInformationAsync(IPAddressipAddress){_Log.Info("Startretrievinginformationsfromaddress"+ipAddress+".");vartcpClient=newTcpClient();tcpClient.BeginConnect(ipAddress,_PortNumber,OnTcpClientConnected,tcpClient);}privatevoidOnTcpClientConnected(IAsyncResultasyncResult){try{using(vartcpClient=(TcpClient)asyncResult.AsyncState){tcpClient.EndConnect(asyncResult);varipAddress=((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address;varstream=tcpClient.GetStream();stream.ReadTimeout=5000;_Log.Debug("连接建立到"+ipAddress+"。");varformatter=newBinaryFormatter();varinformation=(MyInformation)formatter.Deserialize(stream);_Log.Info("成功获取地址信息"+ipAddress+"。");InformationAvailable.FireEvent(这个,新的InformationEventArgs(信息));}}catch(Exceptionex){_Log.Error("获取信息时出错。",前任);返回;}}服务端:publicvoidStart(){ThrowIfDisposed();如果(_TcpServer!=null;)_TcpServer.Stop();_TcpServer=newTcpListener(IPAddress.Any,_PortNumber);_TcpServer.Start();_TcpServer.BeginAcceptTcpClient(OnClientConnected,_TcpServer);_Log.Info("开始侦听传入连接"+_TcpServer.LocalEndpoint+"。");}privatevoidOnClientConnected(IAsyncResultasyncResult){vartcpServer=(TcpListener)asyncResult.AsyncState;IPAddress地址=IPAddress.None;尝试{if(tcpServer.Server!=null&&tcpServer.Server.IsBound)tcpServer.BeginAcceptTcpClient(OnClientConnected,tcpServer);使用(varclient=tcpServer.EndAcceptTcpClient(asyncResult)){address=((IPEndPoint)client.Client.RemoteEndPoint).Address;_Log.Debug("客户端连接地址"+地址+".");varformatter=newBinaryFormatter();varinformations=newMyInformation(){//使用所需值初始化属性。};var流=client.GetStream();格式化程序。序列化(流,描述);_Log.Debug("成功将信息序列化为网络流。");}}catch(ObjectDisposedException){//这通常会发生,当服务器将停止时//并且它们不存在其他可靠的方法来检查此状态//在调用EndAcceptTcpClient()之前。}catch(Exceptionex){_Log.Error(String.Format("无法将实例信息发送到{0}。",address),ex);}}如果客户端失去连接,这段代码可以工作,不会造成任何问题如果你在服务器端失去连接,你必须重新建立监听器,但那是另一回事了。只需要在ReconnectChannel中配置ChannelSocket对象即可。尝试{`//ChannelSocket.Shutdown(SocketShutdown.Both);//ChannelSocket.Disconnect(true);//ChannelSocket.Close();ChannelSocket.Dispose();`}这对我有用。如果它对您不起作用,请告诉我。以上就是C#学习教程的全部内容:如何正常重连socket。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。涉及侵权,请点击维权联系管理员删除。如需转载请注明出处:
