×

c#----------关于tcp客户端连接的问题,如何优雅的连接tcp服务端

zxjy辉 zxjy辉 发表于2023-05-24 10:32:15 浏览344 评论0

抢沙发发表评论

开发了一个软件,使用了tcp协议来交换数据,如何优雅的连接tcp服务端

  1. 问题

    1. 问题一:通常情况下,直接就 new TcpClinet(IP,Port),这样就可以连接到对应的服务器上的TcpListener 单纯这样是可以的,但是,这些都没有考虑到网络的情况,对应的ip和端口是否可以连接,简单的这样连接,会有一个问题,那就是如果对应的IP或则端口有问题,那么连接的时候会有很大的延时或者说是卡住,那么就想能不能添加一个延时,超过一定的时间就直接判断为连接失败呢?(这个才是遇到的主要的问题,其他都是衍生大的问题)

    2. 问题二:再进一步,在连接之前,判断对应的IP是否可以ping通,引入了System.Net.NetworkInformation下的Ping()方法,这个可以检测对应的IP是否是存在的,但是有一个问题,那就是对应的端口是没有办法判断的,如果直接连接,就有可能出现 a 的情况,并且,如果服务器关闭了ping的功能,那这个方法是不是就失效了?

    3. 问题三:如果是连接国外的服务器,设定的时间如果是不刚好,或者是因为网络波动的情况,丢包了,直接使用ping的方法,可能会ping不通

      图片.png图片.png

      在断网的情况下,调用ping方法,会直接报一个异常

  2. 解决的思路

    1. 针对第一个问题,可以采用异步的方法进行连接,取回对应的返回值,然后再这个返回值中设置连接的超时
       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,然后弹窗“连接正常”,所以需要添加一下判断本地网络是否可以联网
    2. 问题二和问题三可以一起解决
      针对这两个问题,一种是问题中提到的直接用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;
      }

  3. 总结

    那就是,如果要提高tcp连接的鲁棒性,那么就需要先判断本地网络的状况以及对应的服务器ip和端口是否可连接,以及设定好超时的时间,如果用到winform,那么尽量使用线程或则是异步连连接网络,不要在主线程连接网络,否则当面板卡住时,点击面板,就会导致面板黑屏闪退

#好好学习!

群贤毕至

访客