处理网络断开连接

5
我正在尝试使用HttpWebRequest对象进行“长轮询”。在我的C#应用程序中,我使用HttpWebRequest发出HTTP GET请求。然后,我使用beginGetResponse()等待响应。我使用ThreadPool.RegisterWaitForSingleObject等待响应或超时(1分钟后)。我已经将目标Web服务器设置为需要很长时间才能响应,这样我就有时间断开网络电缆。发送请求后,我拔掉了网络电缆。是否有一种方法可以在此情况下获得异常?这样我就不必等待超时了。但是,注册等待单个对象的超时会在1分钟超时后发生,而不是抛出异常。是否有一种方法可以确定网络连接已断开?当前,这种情况与Web服务器响应时间超过1分钟的情况无法区分。
3个回答

8
我找到了一个解决方案:
在调用beginGetResponse之前,我可以在HttpWebRequest上调用以下方法:
req.ServicePoint.SetTcpKeepAlive( true, 10000, 1000)

我认为这意味着在10秒的不活动时间后,客户端会向服务器发送一个TCP“keep alive”。如果网络连接断开,因为网络电缆被拔出,那么该保持活动将失败。
所以,当电缆被拔出时,最多在10秒内发送一条保持活动消息,然后回调BeginGetResponse发生。在回调中,当我调用req.EndGetResponse()时,会得到一个异常。
我想这打败了长轮询的其中一个好处。因为我们仍然在发送数据包。

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

2
我不认为你会喜欢这个。在创建请求到缓慢服务器之后,您可以测试互联网连接性。
有许多方法可以实现这一点-从向google.com(或网络中的某个IP地址)发出另一个请求到P/Invoke。您可以在此处获取更多信息:测试互联网连接速度的最快方法 在创建原始请求后,您进入一个循环,检查互联网连接性,直到互联网断开连接或原始请求返回(它可以设置一个变量来停止循环)。
对您有帮助吗?

它有一点帮助,但似乎 HttpWebRequest 应该(早晚)知道它的 TCP 连接是否已断开。 - jm.
为什么不扩展HttpWebRequest以添加此功能?但是,如果您正在询问本机.NET框架,则我认为HttpWebRequest不包含此功能。 - Yannis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接