Question

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

    }
Was it helpful?

Solution

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.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top