C# socket tcp/ip 如何判断连接是否正常
判断socket是否断开连接,网上有N种说法:
1.Socket.Connected
这个属性只能说明上一次通信时还是正常的。 比如说你拔掉网线后就它显示还是为true。用这个方法最好和ping一起组合使用。ping的方法如下
public bool PingOC(String ips) { bool ret; Process p = new Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardInput = true; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.CreateNoWindow = true; int i = 0; p.Start(); p.StandardInput.WriteLine("ping -n 1 " + ips); p.StandardInput.WriteLine("exit"); string strRst = p.StandardOutput.ReadToEnd(); if (strRst.IndexOf("(100%") == -1) { ret = true; } else { ret = false; } p.Close(); return ret; }
2.Socket.Pool
这个方法是可以,但是它要从socket里读或写部分数据,如果其他线程从这个socket读写数据,那么数据将会出错。我在写一个远程通信软件时候就出现这个问题了。
而且http://technet.microsoft.com/zh-cn/system.net.sockets.socket.poll.aspx上这样说的:
此方法不能检测某些类型的连接问题,例如,网络电缆中断或远程主机意外关闭。您必须尝试发送或接收数据以检测这些类型的错误。
3.使用心跳包
每隔一段时间,socket一方向另一方发送一段特殊的数据,socket的另一方接到这个数据后回发回来。这样就能判断socket两方都没有掉线了。
4.判断Socket是否连接上,需要通过发包来确认: (这个方法也不能解决物理掉线问题,比如拔网线)
// 检查一个Socket是否可连接 private bool IsSocketConnected(Socket client) { bool blockingState = client.Blocking; try { byte[] tmp = new byte[1]; client.Blocking = false; client.Send(tmp, 0, 0); return false; } catch (SocketException e) { // 产生 10035 == WSAEWOULDBLOCK 错误,说明被阻止了,但是还是连接的 if (e.NativeErrorCode.Equals(10035)) return false; else return true; } finally { client.Blocking = blockingState; // 恢复状态 } }
5.利用keepalive检测。
具体代码方法见:https://www.cnblogs.com/wzd24/archive/2007/05/22/755050.html https://www.cnblogs.com/legendtao/p/4930098.html
手动设置注册表的方法:https://blog.csdn.net/chenjianqi0502/article/details/78490295 。
具体工作中大家根据实际情况选择合适方法。我一般选择第一种+ping的方法即可。