Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling network disconnect

Tags:

c#

I am trying to do "long polling" with an HttpWebRequest object.

In my C# app, I am making an HTTP GET request, using HttpWebRequest. And then afterwards, I wait for the response with beginGetResponse(). I am using ThreadPool.RegisterWaitForSingleObject to wait for the response, or to timeout (after 1 minute).

I have set the target web server to take a long time to respond. So that, I have time to disconnect the network cable.

After sending the request, I pull the network cable.

Is there a way to get an exception when this happens? So I don't have to wait for the timeout?

Instead of an exception, the timeout (from RegisterWaitForSingleObject) happens after the 1 minute timeout has expired.

Is there a way to determine that the network connection went down? Currently, this situation is indistinguishable from the case where the web server takes more than 1 minute to respond.

like image 662
jm. Avatar asked Feb 09 '12 18:02

jm.


2 Answers

I found a solution:

Before calling beginGetResponse, I can call the following on the HttpWebRequest:

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

I think this means that after 10 seconds of inactivity, the client will send a TCP "keep alive" over to the server. That keep alive will fail if the network connection is down because the network cable was pulled.

So, when the cable is pulled, I a keep alive gets sent within 10 seconds (at most), and then the callback for BeginGetResponse happens. In the callback, I get and exception when I call req.EndGetResponse().

I guess this defeats one of the benefits of long polling, though. Since we're still sending packets around.

like image 158
jm. Avatar answered Sep 19 '22 02:09

jm.


I'll leave it to you to try pulling the plug on this.

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();
}
like image 34
Aaron Anodide Avatar answered Sep 21 '22 02:09

Aaron Anodide