【问题标题】:Handling network disconnect处理网络断开连接
【发布时间】:2012-02-09 18:45:51
【问题描述】:

我正在尝试使用 HttpWebRequest 对象进行“长轮询”。

在我的 C# 应用程序中,我正在使用 HttpWebRequest 发出 HTTP GET 请求。然后,我用 beginGetResponse() 等待响应。我正在使用 ThreadPool.RegisterWaitForSingleObject 等待响应或超时(1 分钟后)。

我已将目标 Web 服务器设置为需要很长时间才能响应。这样,我就有时间断开网线了。

发送请求后,我拉网线。

发生这种情况时有没有办法获得异常?这样我就不用等超时了?

超时(来自 RegisterWaitForSingleObject)不是异常,而是在 1 分钟超时后发生。

有没有办法确定网络连接断开了?目前,这种情况与网络服务器响应时间超过 1 分钟的情况没有区别。

【问题讨论】:

    标签: c#


    【解决方案1】:

    我找到了解决办法:

    在调用 beginGetResponse 之前,我可以在 HttpWebRequest 上调用以下内容:

    req.ServicePoint.SetTcpKeepAlive( true, 10000, 1000)
    

    我认为这意味着在 10 秒不活动后,客户端将向服务器发送 TCP“保持活动”。如果网络连接因网络电缆被拔出而中断,则保持活动将失败。

    因此,当电缆被拉出时,我会在 10 秒内(最多)发送一个 keep alive,然后发生 BeginGetResponse 的回调。在回调中,当我调用 req.EndGetResponse() 时出现异常。

    不过,我想这会破坏长轮询的好处之一。因为我们仍在发送数据包。

    【讨论】:

      【解决方案2】:

      我会留给你尝试拔掉这个插头。

      ManualResetEvent done = new ManualResetEvent(false);
      
      void Main()
      {        
          // set physical address of network adapter to monitor operational status
          string physicalAddress = "00215A6B4D0F";
      
          // create web request
          var request = (HttpWebRequest)HttpWebRequest.Create(new Uri("http://stackoverflow.com"));
      
          // create timer to cancel operation on loss of network
          var timer = new System.Threading.Timer((s) => 
          {
              NetworkInterface networkInterface = 
                  NetworkInterface.GetAllNetworkInterfaces()
                      .FirstOrDefault(nic => nic.GetPhysicalAddress().ToString() == physicalAddress);
      
              if(networkInterface == null)
              {
                  throw new Exception("Could not find network interface with phisical address " + physicalAddress + ".");
              }
              else if(networkInterface.OperationalStatus != OperationalStatus.Up)
              {
                  Console.WriteLine ("Network is down, aborting.");
                  request.Abort();
                  done.Set();
              }
              else
              {
                  Console.WriteLine ("Network is still up.");
              }
          }, null, 100, 100);
      
          // start asynchronous request
          IAsyncResult asynchResult = request.BeginGetResponse(new AsyncCallback((o) =>
          {
              try
              {           
                  var response = (HttpWebResponse)request.EndGetResponse((IAsyncResult)o); 
                  var reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
                  var writer = new StringWriter();
                  writer.Write(reader.ReadToEnd());
                  Console.Write(writer.ToString());
              }
              finally
              {
                  done.Set();
              }
          }), null);
      
          // wait for the end
          done.WaitOne();
      }
      

      【讨论】:

        【解决方案3】:

        我不认为你会喜欢这个。创建对慢速服务器的请求后,您可以测试 Internet 连接。

        有很多方法可以做到这一点 - 从另一个请求到 google.com(或您网络中的某个 IP 地址)到 P/Invoke。您可以在这里获取更多信息:Fastest way to test internet connection

        创建原始请求后,您将进入一个检查互联网连接的循环,直到互联网关闭或原始请求返回(它可以设置一个变量来停止循环)。

        有帮助吗?

        【讨论】:

        • 它有点帮助,但似乎 HttpWebRequest 应该(迟早)知道它的 TCP 连接是否已断开。
        • 为什么不扩展 HttpWebRequest 来添加这个功能呢?但如果您询问的是原生 .NET 框架,那么不,我认为 HttpWebRequest 不包含这样的功能。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-27
        相关资源
        最近更新 更多