6

I need to poll a server, which is running some propriatary software, to determine if this service is running. Using wireshark, I've been able to narrow down the TCP port its using, but it appears that the traffic is encrypted.

In my case, its a safe bet that if the server is accepting connections (i.e. telnet serverName 1234) the service is up and all is OK. In other words, I don't need do any actual data exchange, just open a connection and then safely close it.

I'm wondering how I can emulate this with C# and Sockets. My network programming basically ends with WebClient, so any help here is really appreciated.

Nate
  • 30,286
  • 23
  • 113
  • 184

4 Answers4

10

The process is actually very simple.

using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
    try
    {
        socket.Connect(host, port);
    }
    catch (SocketException ex)
    {
        if (ex.SocketErrorCode == SocketError.ConnectionRefused) 
        {
            // ...
        }
    }
}
ChaosPandion
  • 77,506
  • 18
  • 119
  • 157
  • Is there a way to adjust the connect timeout? It seems to fail, but only after about a minute... – Nate May 14 '10 at 18:51
  • @Nate I believe that is how long the process takes. There is no connection timeout option. – ChaosPandion May 14 '10 at 18:57
  • I added `if(ex.SocketErrorCode == SocketError.ConnectionRefused || ex.SocketErrorCode == SocketError.TimedOut)` – Nate May 14 '10 at 19:00
  • While it looks good and simple, I have strong suspicions regarding performance drop on the server. Suppose it has a handler for new clients coming (and going), it will be triggered additionally whenever client performs such a check. Isn't there more elegant way in C# 9 years later? Ideally event based (it is easy to create event wrapper for this, but, again, it will have consequences for the server) – Do-do-new Jul 29 '19 at 12:53
3

Just use TcpClient try to connect to the server, TcpClient.Connect will throw an exception if the connection fails.

bool IsListening(string server, int port)
{
    using(TcpClient client = new TcpClient())
    {
        try
        {
            client.Connect(server, port);
        }
        catch(SocketException)
        {
            return false;
        }
        client.Close();
        return true;
    }
}
Phil Lamb
  • 1,407
  • 10
  • 15
  • Is there a way to adjust the connect timeout? It seems to fail, but only after about a minute... – Nate May 14 '10 at 18:51
2

I've used the following code. There is one caveat ... in a high transaction environment, the client's available ports may run out as the sockets are not released by the OS at the same rate they are released by the .NET code.

If anyone's got a better idea, please post. I've seen snowball issues arise where the server can no longer make outgoing connections. I'm working on a better solution ...

public static bool IsServerUp(string server, int port, int timeout)
    {
        bool isUp;

        try
        {
            using (TcpClient tcp = new TcpClient())
            {
                IAsyncResult ar = tcp.BeginConnect(server, port, null, null);
                WaitHandle wh = ar.AsyncWaitHandle;

                try
                {
                    if (!wh.WaitOne(TimeSpan.FromMilliseconds(timeout), false))
                    {
                        tcp.EndConnect(ar);
                        tcp.Close();
                        throw new SocketException();
                    }

                    isUp = true;
                    tcp.EndConnect(ar);
                }
                finally
                {
                    wh.Close();
                }
            } 
        }
        catch (SocketException e)
        {
            LOGGER.Warn(string.Format("TCP connection to server {0} failed.", server), e);
            isUp = false;
        }

        return isUp;
ZaChickster
  • 430
  • 1
  • 8
  • 14
0

Use the TcpClient class to connect the server.

compie
  • 10,135
  • 15
  • 54
  • 78