tags:

views:

157

answers:

4

When running the following Java code, I get very accurate and consistent results in determining if the web page I'm testing is up.

protected synchronized boolean checkUrl(HttpURLConnection connection){
 boolean error = false;
 //HttpURLConnection connection = null;
 GregorianCalendar calendar = new GregorianCalendar();

 try{
  if(connection != null){
   connection.connect();

   //200 is the expected HTTP_OK response
   error = processResponseCode(connection.getResponseCode());

   connection.disconnect();
  } else{
   error = false;
  }

 }catch(java.net.UnknownHostException uhe){
  ...  } 
 catch(Exception e){
  ...  }

 return error;
}

The closest match to the Java pattern in c# has much higher results of false positives (mostly due to timeouts - which has a default period of 100000ms).

protected bool connectedToUrl = false;
        response = null;

        HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(this.getUri());
        webreq.Credentials = CredentialCache.DefaultCredentials;
        WebResponse res = null;// webreq.GetResponse();

        try
        {
            WebRequest request = WebRequest.Create(this.getUri()) as WebRequest;
            request.Credentials = CredentialCache.DefaultCredentials;

            if (request != null)
            {
                // Get response 
                res = webreq.GetResponse();

                connectedToUrl = processResponseCode(res);
            }
            else
            {
                logger.Fatal(getFatalMessage());

                string error = string.Empty;
            }
        }
        catch (Exception e)
        {
            throw e;
        }

        return connectedToUrl;
    }

I have tried various patterns in c# to match the effectiveness of the quoted Java code, to no avail.

Any ideas?

+3  A: 

I believe this is because you're not closing any of the request objects.

krosenvold
Would they not just go out of scope?
steve_mtl
No, it's not enough. Make sure you call *any* close method you can find on all the http-related objects you use ;)
krosenvold
There's some pooling going, which is the reason you have to close.
krosenvold
put a using block around the request?
ccook
A: 

I think you're missing the GregorianCalendar in the C# version :-)

Why do you have two Request Objects in the C# version?

Jason Punyon
LOL. That's the best diagnosis I've seen today.
krosenvold
I'm working on it, just waiting for my submission to be incorporated in framework 5. ;)
steve_mtl
I have 2 objects because one should have been commented out. Its the 4th iteration and had a few sloppy artifacts.
steve_mtl
+1  A: 

Also this:

   catch (Exception e)
   {
      throw e;
   }

Does nothing but destroy the stack trace on an exception that's been bubbled upwards. If you have error handling elsewhere in your code I suggest removing the try catch block. Otherwise you should log the exception and move on. Don't just catch it to throw it.

Spencer Ruport
Or, when rethrowing use the proper syntax: http://stackoverflow.com/questions/380819/common-programming-mistakes-for-net-developers-to-avoid#380833
lacop
+1  A: 

Simply change this:

res = webreq.GetResponse();
connectedToUrl = processResponseCode(res);

to

using (WebResponse res = webreq.GetResponse()) 
{
    connectedToUrl = processResponseCode(res);
}

(Remove the declaration from earlier.)

Until you haven't closed/disposed the response (or it's been finalized), it's holding onto the connection. You can only have a certain number (2 by default, I believe) of connections to any one host at a time, hence the timeouts. When you dispose the response, it allows another request to use the same connection.

Jon Skeet
the processResponseCode is looking to the response code (401, 404, 200,...) when checking the URL.
steve_mtl
Oh, true. Editing...
Jon Skeet
So should I add "res.Close();" inside the using(...) block?
steve_mtl
No - the point of the using statement is that it's like a try/finally which calls Dispose in the finally block.
Jon Skeet
Update: the timeouts are gone.
steve_mtl