Concurrent and interruptible DNS name resolution of multiple names seems impossible

StackOverflow https://stackoverflow.com/questions/21734655

  •  10-10-2022
  •  | 
  •  

Domanda

I need to quickly test a list of ~100 web servers for connectivity. Quickly means around 5 seconds for the whole bunch. If a server is inaccessible for about 2-3 seconds, it should be skipped. If there's no internet connection - the test should fail quickly - 2-3 seconds. It should run on XP (SP2) and up.

I decided to run a test procedure for each server in a separate thread.

Synchronous test procedure does the following:

  • gethostbyname() or getaddrinfo() (tried both)
  • creates a socket
  • connect()
  • send HTTP request
  • read HTTP responce (just half a kilobyte of it)

This is no good:

  • in case of a slow server the connect() is blocking with no timeout.
  • in case of no internet connection - gethostbyname() and getaddrinfo() block for a long time: 17+ seconds.

Asynchronous test procedure:

  • create window for async messages
  • WSAAsyncGetHostByName() - to receive a message when resolution is complete
  • WSAAsyncSelect() - to receive connect, ready-to-send and ready-to-read messages
  • SetTimeout() to receive a timeout message and eject
  • runs a message loop for the window

This one is also no good because WSAAsyncGetHostByName() "is not designed to provide parallel resolution of several names" (MSDN). And so, it does sequential resolution even when called from multiple threads. This makes the threads run sequentially defeating their purpose.

Hence my problem: either blocking calls that cannot be interrupted or asynchronous calls that can't be paralellized.

Seems to me that the only option is to do the blocking calls in separate threads, and if a thread does not finish quickly enough - murder it with TerminateThread().

Anything better than that?!

È stato utile?

Soluzione

I'm not sure this fits your model, but maybe you can resolve the IP addresses of the hostnames once, as a cold start kind of thing, and then cache them.

That way, you avoid having to use WSAAsyncGetHostByName which is the bottleneck, and you only need to test out the HTTP communication.

Now, assuming you have reason to suspect that a certain host has changed its IP address since you last resolved it (say, the destination was unreachable, or the connection refused), you can simply run a query again for that host.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top