2012-02-09 89 views
4

我想用HttpWebRequest对象进行“长轮询”。处理网络断开

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

我已经设置了目标Web服务器需要很长时间才能响应。所以,我有时间断开网线。

发送请求后,我拉网线。

当发生这种情况时,是否有办法获得异常?所以我不必等待超时?

而不是一个例外,超时(从RegisterWaitForSingleObject)发生在1分钟超时已过期后。

有没有办法确定网络连接故障?目前,这种情况与Web服务器花费1分钟以上的时间进行响应的情况没有区别。

回答

8

我找到了一个解决方案:

在致电beginGetResponse,我可以呼吁HttpWebRequest的以下内容:

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

我认为,这意味着闲置10秒后,客户端会发送一个TCP“保持活跃”到服务器。如果网络连接因网络电缆被拉断而关闭,则保持活动状态将失败。

所以,当拉线时,我保持活着在10秒内(最多)发送,然后发生BeginGetResponse的回调。在回调中,当我调用req.EndGetResponse()时,我会得到和异常。

我想这会打败长轮询的好处之一。由于我们仍在发送数据包。

2

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

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

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

有帮助吗?

+0

它有一点帮助,但它似乎像HttpWebRequest应该知道(迟早)如果它的TCP连接已经关闭。 – 2012-02-09 19:27:05

+0

为什么不扩展HttpWebRequest以添加此功能?但如果你问的是本地.NET框架,那么不,我不认为HttpWebRequest包含这样的功能。 – Yannis 2012-02-09 19:37:16

3

我会让你尝试拉上这个插件。

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(); 
}