2

I'm trying to establish a socket connection to a host/ip address for a specific port. The main things I try to achieve are:

  • get the response time in milliseconds for booth success/fail connection
  • use a custom timeout for example 5 seconds (5000)

So basically if I specify a host name like google.com and port 80 this should check if connection works, the same if I specify 173.194.70.101 and port 80 it should work.

If I specify for example host name like google.com and port 7788 this should not work because that port is not open. If I specify IP: 173.194.70.101 and port ´7788´ this should not work.

If I specify some random host like sdfzsdfaklsf.com and port 7788 this should not work because the host doesn't exist.

For all the cases above I need the response time for all success/fail ...

I ended up with this code and seams to work fine, however I would like to ask if this is a proper way of doing it?

     public string CheckConnection(string ipAddressOrHostName, string portName)
    {
        Stopwatch timer = new Stopwatch();
        timer.Start();
        Socket server = null;
        string elapsed = string.Empty;

        try
        {

            IPHostEntry hostEntry = Dns.GetHostEntry(ipAddressOrHostName);

            IPAddress ipAddress = hostEntry.AddressList[0];

            IPEndPoint ip = new IPEndPoint(ipAddress, Convert.ToInt32(portName));

            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IAsyncResult result = server.BeginConnect(ip, null, null);

            result.AsyncWaitHandle.WaitOne(5000, true);

            timer.Stop();

            elapsed = timer.ElapsedMilliseconds.ToString();


            if (!server.Connected)
            {                    
                server.Close();
                throw new Exception();
            }
            else
            {   
                string status = string.Format("Connected succesfully to: {0} in: {1} milliseconds", server.RemoteEndPoint.ToString(), elapsed);                   
                server.Shutdown(SocketShutdown.Both);
                server.Close();

                return status;
            }
        }
        catch (Exception)
        {
            timer.Stop();

            elapsed = timer.ElapsedMilliseconds.ToString();

            return string.Format("Connection failed to: {0}:{1} in: {2} milliseconds", ipAddressOrHostName, portName, elapsed);                     
        }

    }
1
  • I would improve your exception handling. Catching a generic exception and treating as a specific network/connection failure is not recommended. Also try putting your close/shutdown/stop calls into a 'finally' block.... beside that, I think that looks fine.. Commented Aug 27, 2013 at 20:43

1 Answer 1

2

It's pretty good. A few points:

  1. Catch a more specific type of exception and test it. You don't want to catch unrelated stuff or hide bugs.
  2. Start the timer after you have completed the DNS resolution.
  3. throw new Exception is not so good because exceptions are not meant as control flow. Restructure the method to not need this hack.
  4. You might want to use tasks instead of IAsyncResult. No functional change, just more modern style.
  5. You have redundancy in a few places (e.g. the duplicate closing, duplicate ToString).
  6. Parse the port outside of the method. It does not belong there. In fact, if the port is unparsable you will trigger a perceived timeout at the moment because an exception will be thrown. That's what I am warning you of with point (1). Using exceptions too much has caused a bug that you maybe would never have known about because it was hidden.
Sign up to request clarification or add additional context in comments.

4 Comments

Can you please tell how can I implement async await instead of IAsyncResult?
I think that's out of scope for this question. Search for "await socket" to find the answer. If you have further questions let me know.
I did implemented async-await instead of IAsyncResult, but I loose the control of the custom timeout which by default is 20 seconds i think ... but anyway thanks for your comments!
To be clear I do not recommend await here. I just recommended tasks without await (e.g. Task.Wait(5000)). But that is just a weak preference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.