Check if an indy Http server is active by indy client issue!

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Check if an indy Http server is active by indy client issue!

Postby Ahmed Sayed » Tue Mar 12, 2019 7:53 am

Hi I am creating an app to monitor some of my http servers so in case they are down I get notified by email.

I used this code to check for the connection if it is active or not:

Code: Select all
bool SocketIsOpen( UnicodeString Host, int Port, String &Msg, int ATimeout)
{
unique_ptr<TIdTCPClient> Socket(new TIdTCPClient(nullptr));
Msg = "";
bool res = false;
try
   {
   Socket->ConnectTimeout = ATimeout;
   try
      {
      Socket->Connect( Host, Port);
      res = Socket->Connected();
      }
   catch (const Exception &E)
      {
      Msg = E.Message;
      res = false;
      }
   }
__finally
   {
   Socket->Disconnect();
   }
return res;
}
//---------------------------------------------------------------------------


I used this function periodically every 500 MS and the timeout is 1 MS but sometimes I get Connection timeout. The monitoring app and the servers are on the same machine so i don't think there should be any timeouts. The server itself is active all the time.

Actually what I am trying to do is monitor the following for each server:
Memory - CPU usage - No. Connections - Threads - detect if server is responding or not - TIdHttpServer is active or not

The reason why I use 1 Ms as timeout is that I don't want all the previous checks take a lot of time. There is an interval of 500 Ms between a check is made on all server process and the next check.

For example, if I have 4 servers running above data is collected for each server then wait for 500 Ms and then collect data for all servers again.

So is their a way to do so with speed with no timeouts.
Thanks in advance
Ahmed Sayed
Active Poster
Active Poster
 
Posts: 24
Joined: Thu Nov 08, 2018 4:12 pm

Re: Check if an indy Http server is active by indy client is

Postby mark_c » Wed Mar 13, 2019 12:01 am

always if I understand your problem: and setting a timeout of 100 ms instead of 1 ms what happens?
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 154
Joined: Thu Jun 21, 2012 1:13 am

Re: Check if an indy Http server is active by indy client is

Postby Ahmed Sayed » Fri Mar 15, 2019 7:39 am

If i changed the timeout to 100 MS sure the process will get slower and it still timeout from time to time like giving me 7 timeouts in 1 minute during monitoring 4 servers.
Ahmed Sayed
Active Poster
Active Poster
 
Posts: 24
Joined: Thu Nov 08, 2018 4:12 pm

Re: Check if an indy Http server is active by indy client is

Postby rlebeau » Wed Apr 17, 2019 1:19 pm

Ahmed Sayed wrote:If i changed the timeout to 100 MS sure the process will get slower and it still timeout from time to time like giving me 7 timeouts in 1 minute during monitoring 4 servers.


That is to be expected, as even 100ms may be too short at times. There is overhead in establishing a new TCP connection (3-way handshake), as well as overhead in how Indy implements its ConnectTimeout (using a worker thread). So, you really should specify a timeout in seconds rather than in milliseconds.

For that matter, since you are doing real-time monitoring, why drop a connection and reconnect at 500ms intervals at all? Why not just establish a connection and leave it open? You will be notified if the connection is closed, such as when the server is shut down or killed.

Otherwise, I would suggest using the socket API directly to cut down on overhead, eg:

Code: Select all
#include <winsock2.h>
#include <ws2tcpip.h>
#include <vector>
#include <memory>

struct SocketDeleter
{
    typedef SOCKET pointer;

    void operator()(SOCKET s) const
    {
        if (s != INVALID_SOCKET)
        {
            int err = WSAGetLastError();
            closesocket(s);
            WSASetLastError(err);
        }
    }
};

bool SocketIsOpen(const UnicodeString &Host, short Port, String &Msg, int ATimeout)
{
    Msg = _D("");

    try
    {
        ADDRINFOW hints = {}, *addrs;

        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;

        if (GetAddrInfoW(Host.c_str(), UnicodeString(Port).c_str(), &hints, &addrs) != 0)
            RaiseLastOSError(WSAGetLastError());

        std::vector<std::unique_ptr<SOCKET, SocketDeleter>> sockets;

        {
        std::unique_ptr<ADDRINFOW, decltype(&::FreeAddrInfoW)> addrs_deleter(addrs, &FreeAddrInfoW);

        for (ADDRINFOW *addr = addrs; addr != NULL; addr = addr->ai_next)
        {
            SOCKET sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
            if (sock != INVALID_SOCKET)
            {
                std::unique_ptr<SOCKET, SocketDeleter> sock_deleter(sock);

                u_long mode = 1;
                if (ioctlsocket(sock, FIONBIO, &mode) == 0)
                {
                    connect(sock, addr->ai_addr, addr->ai_addrlen);
                    if (WSAGetLastError() == WSAEWOULDBLOCK)
                        sockets.push_back(std::move(sock_deleter));
                }
            }
        }

        if (sockets.empty())
            RaiseLastOSError(WSAGetLastError());
        }

        fd_set fds;
        FD_ZERO(&fds);
        for(auto &sock : sockets) {
            FD_SET(sock.get(), &fds);
        }

        timeval tv = {};
        tv.tv_sec = ATimeout / 1000;
        tv.tv_usec = (ATimeout & 1000) * 1000;

        int err = select(0, NULL, &fds, NULL, &tv);
        if (err < 0)
            RaiseLastOSError(WSAGetLastError());

        return (err > 0);
    }
    catch (const Exception &E)
    {
        Msg = E.Message;
        return false;
    }
}
//---------------------------------------------------------------------------
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1588
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Check if an indy Http server is active by indy client is

Postby Ahmed Sayed » Wed Apr 17, 2019 1:56 pm

For that matter, since you are doing real-time monitoring, why drop a connection and reconnect at 500ms intervals at all? Why not just establish a connection and leave it open? You will be notified if the connection is closed, such as when the server is shut down or killed.

You mean using a TIdTCPClient or so and leave the connection open but the server i am monitoring is REST server so there is no KeepAlive enabled for this one. Is it possible to make a client force a server to keep the connection open even if the server KeepAlive property is false?
Ahmed Sayed
Active Poster
Active Poster
 
Posts: 24
Joined: Thu Nov 08, 2018 4:12 pm

Re: Check if an indy Http server is active by indy client is

Postby rlebeau » Wed Apr 17, 2019 4:53 pm

Ahmed Sayed wrote:You mean using a TIdTCPClient or so and leave the connection open


Yes. Then you can monitor the state of that connection, rather than wasting time and resources tearing down connections and recreating them on a regular basis.

Ahmed Sayed wrote:but the server i am monitoring is REST server so there is no KeepAlive enabled for this one.


Then have your server open another port that your monitoring app can connect to. This also gives you the benefit of having the server app monitor its own vitals and report them to monitoring clients as needed, instead of having the clients try to figure out what is going on.

Ahmed Sayed wrote:Is it possible to make a client force a server to keep the connection open even if the server KeepAlive property is false?


Not in the HTTP protocol, no. But that doesn't mean you have to limit your server to just HTTP. Or, you could open multiple HTTP ports, where REST without KeepAlive is on one port, and monitoring with KeepAlive is on another port.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1588
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Check if an indy Http server is active by indy client is

Postby Ahmed Sayed » Wed Apr 17, 2019 5:39 pm

Thanks, But how can check the status of the client connection? and how can create another port for TIdHTTPServer with keepalive enabled for that server? or do i have to place another server component for monitoring. because the idea is to monitor that specific server.
Ahmed Sayed
Active Poster
Active Poster
 
Posts: 24
Joined: Thu Nov 08, 2018 4:12 pm

Re: Check if an indy Http server is active by indy client is

Postby rlebeau » Wed Apr 17, 2019 10:47 pm

Ahmed Sayed wrote:how can check the status of the client connection?


Perform I/O on it periodically and check for errors.

Ahmed Sayed wrote:how can create another port for TIdHTTPServer with keepalive enabled for that server?


Use separate TIdHTTPServer instances. Or, use a single TIdHTTPServer instance with multiple Bindings assigned and KeepAlive enabled, then in the OnCommand... event(s) you can set AResponseInfo.CloseConnection based on which Binding port received the request.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1588
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA


Return to Technical

Who is online

Users browsing this forum: No registered users and 26 guests

cron