Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 May : Re: Broadcasting messages with Indy

www.cryer.info
Managed Newsgroup Archive

Re: Broadcasting messages with Indy

Subject:Re: Broadcasting messages with Indy
Posted by:"Martin James" (mjames_falc..@dial.pipex.com)
Date:Thu, 18 May 2006 13:26:30

"David Hooker" <david.d.hooker@gmail.com> wrote in message
news:446c12b2@newsgroups.borland.com...
> Is there a way to send the same message to many other computers in
> parallel using Indy without requiring a thread per connection?
>
> For example, say I have an enourmous array of connections and I want to
> send the same message to them all (but all of these connections are to
> other addresses on the Internet, so I would expect that UDP broadcasts
> wouldn't work).  I would like to send all messages at the same time.

Oh dear...

> Using one thread to send all the messages seems to require that all
> messages be sent in series.  I think that this option would be prone to
> bad/flakey connections and might require tens of seconds to timeout and
> be ready to send to the next connection in the array.

That can be a problem with simple 'loop over all the other contexts in the
list and call a write method for each one'.  If one client has become
unreachable and enough data is sent to fill up write buffering, then the
write call will block until the TCP retries etc. timer/s have expired.

> On the other hand, requiring one or two threads per connection would
> require a lot of resources, even if most threads are blocked most of
> the time.

Indy, (currently) has one thread per connection anyway, but it is
annoying/wasteful to have to create another to do writes.  There are some
solutions that have been used:

1) A short-timeout on read calls in the peer threads/contexts, allowing a
thread-safe queue to be polled by the context/thread.  This works but wastes
CPU and adds latency, in inverse proportions to the length of the timeout.
2)  Convert the blocking socket to non-blocking and wait on both the socket
and a producer-consumer queue.  This removes the CPU waste/latency but
introduces non-blocking state-machines to handle such events as
'wsa_would_block'.

3) Use a small pool of threads to do the writes and queue the write buffers
and the context to this pool.  This works but is more complex and only
allows [no. of write threads-1] connections to go bad before the write
system gets stuck and further writes to good connections just queue up
because all the write threads are timing out.

As Remy pointed out in another post recently, these schemes may become
problematic with developing versions of Indy that have only a few
'protocol-handler' threads that run a much greater number of socket objects.
Tineouts in such a design would have to be implemented by a complex
inter-thread signalling mechanism where the contexts are amongst other
things, queued in a seperate timeout-handler thread.  Short timeouts in such
a design would be very costly indeed.

On top of all this, there is the problem of sending the same message to all
clients.  If you do not want to make 'enormous' numbers of copies of each
message, each message will need a threadSafe refCount to detect when all the
writes have been completed.  This ref. would have to be decremented and
tested after each write/exception/disconnect/whatever so that it can be
freed or repooled only when every client context has dealt with it.

I'm afraid that this 'broadcast' requirement is a bit messy no matter how
you try to implement it.

Rgds,
Martin

Replies:

none

In response to:

www.cryer.info
Managed Newsgroup Archive