开发了一个软件,使用了tcp协议来交换数据,如何优雅的连接tcp服务端
问题
问题一:通常情况下,直接就 new TcpClinet(IP,Port),这样就可以连接到对应的服务器上的TcpListener 单纯这样是可以的,但是,这些都没有考虑到网络的情况,对应的ip和端口是否可以连接,简单的这样连接,会有一个问题,那就是如果对应的IP或则端口有问题,那么连接的时候会有很大的延时或者说是卡住,那么就想能不能添加一个延时,超过一定的时间就直接判断为连接失败呢?(这个才是遇到的主要的问题,其他都是衍生大的问题)
问题二:再进一步,在连接之前,判断对应的IP是否可以ping通,引入了System.Net.NetworkInformation下的Ping()方法,这个可以检测对应的IP是否是存在的,但是有一个问题,那就是对应的端口是没有办法判断的,如果直接连接,就有可能出现 a 的情况,并且,如果服务器关闭了ping的功能,那这个方法是不是就失效了?
问题三:如果是连接国外的服务器,设定的时间如果是不刚好,或者是因为网络波动的情况,丢包了,直接使用ping的方法,可能会ping不通


在断网的情况下,调用ping方法,会直接报一个异常
解决的思路
针对第一个问题,可以采用异步的方法进行连接,取回对应的返回值,然后再这个返回值中设置连接的超时 var client = new TcpClient(); var result = client.BeginConnect("11.22.33.44", 10608, null, null); var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(0.1)); if (!success) { MessageBox.Show("连接失败"); } else { MessageBox.Show("连接正常"); } ///Ps:在这里如果是断网的情况下进行的连接,其返回值也是true,然后弹窗“连接正常”,所以需要添加一下判断本地网络是否可以联网问题二和问题三可以一起解决 针对这两个问题,一种是问题中提到的直接用ping的方式,然后使用try catch捕获异常,表示连接失败,这也是一种办法 办法二就是: 引入一个命名空间中,使用window自带的动态连接库sensapi.dll检测本地网络是否连接 using System.Runtime.InteropServices; //用于检测判断网络是否联通 [DllImport("sensapi.dll")] private extern static bool IsNetworkAlive(out int connectionDescription); //导入库 private string Fun_IsNetworkAlive() { int NETWORK_ALIVE_LAN = 0; int NETWORK_ALIVE_WAN = 2; int NETWORK_ALIVE_AOL = 4; string outPut = null; //上网方式 int flags; //是否在线 bool m_bOnline = true; m_bOnline = IsNetworkAlive(out flags); //在线 if (m_bOnline) { if ((flags & NETWORK_ALIVE_LAN) == NETWORK_ALIVE_LAN) { outPut = "联机:LAN"; } if ((flags & NETWORK_ALIVE_WAN) == NETWORK_ALIVE_WAN) { outPut = "联机:WAN"; } if ((flags & NETWORK_ALIVE_AOL) == NETWORK_ALIVE_AOL) { outPut = "联机:AOL"; } } else { outPut = "脱机:NoOnLine"; } return outPut; }总结
那就是,如果要提高tcp连接的鲁棒性,那么就需要先判断本地网络的状况以及对应的服务器ip和端口是否可连接,以及设定好超时的时间,如果用到winform,那么尽量使用线程或则是异步连连接网络,不要在主线程连接网络,否则当面板卡住时,点击面板,就会导致面板黑屏闪退
#好好学习!