Re: Thread safety of asynchronous sockets, also - documentation vs reality

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



I have been pondering this same set of issues (including the very
misleading documentation), and this discussion has helped to complete my
understanding (particularly on the issue of EndReceive blocking, and why
that would ever occur).

The thread itself, however, still seems to have a few pieces missing. I
now think that I have a fairly complete picture of the matter, and that
picture is presented below for your consideration and comment.

The key point that seems to have been overlooked so far in our
discussion is: Why go to all the trouble of using BeginReceive() /
EndReceive(), callbacks, etc., when you could just create your own
worker thread for each client connection and then use synchronous
methods (i.e., Receive) within that thread for monitoring incoming data
from the client?

I believe that the answer is that the BeginReceive() / EndReceive()
approach requires vastly fewer threads than the
one-worker-thread-per-client approach.

But, how could this be the case if "BeginReceive creates it's own thread
which will not call your callback until data is available" (as one
poster stated)? If BeginReceive created its own thread, then there
would be a thread sitting there for the entire duration of the client's
think-type (or other kind of) delay, and when your callback function was
called, it would run on that thread and then would immediately create a
*new* thread before it exited (to wait for any subsquent input).

So, you would still have one thread for each connected client. And, you
would have the *additional* overhead of stopping and starting a thread
for each fragment of input received. Therefore, if a new thread is
being created by BeginReceive(), then why would you want to use
BeginReceive() / EndReceive() (instead of a worker thread that calls the
synchronous Receive() method) if the main point of using the former is
to reduce the number of threads required by a server application?

This is still just a theory (given the lack of good documentation), but
here is what I think is going on:

When you use BeginReceive(), passing it a callback, *no* new thread is
created at that time. Instead, the framework makes a note of the
callback, the port to be monitored, the buffer location, etc., and then
watches that port for input *without* creating an additional thread.
I'm not sure exactly what Framework/OS mechanisms are used to accomplish
this watching, but I don't think it requires its own worker thread, as
clearly the requirements for saving state for this task are
significantly less than those for a typical thread (which needs a stack
for local variables, current program counter location, priority, etc.,
etc.).

When input eventually appears on the port, a thread is allocated *then*
from the existing (reusable) thread pool, and your callback method is
run on that thread. Your callback should be written so that it does not
block. As a
result, your callback will complete very rapidly, obtaining whatever
data was read by calling EndReceive(), processing it, calling
BeginReceive() again if there is more input, and then terminating. Each
time your callback completes,
the thread on which it is running is returned to the thread pool.

This means that you are tying up a thread only during the time that your
callback is actually running. Between the increments of client input
data, there is *no* active thread.

So, say that you are running a chat application with thousands of
simultaneous client (user) connections. Let's say that 99 percent of
the time of these users is spent thinking and typing, and when they hit
the Enter key for each chat message, it takes only about one hundreth of
the
time to process that input as it did for them to think it up and type
it. Then, we will have one one-hundreth of the threads running using
the BeginReceive() / EndReceive() approach that we would have had if we
had allocated a new thread for each client connection and waited
synchronously on that thread for input to arrive.

That is a huge increase in efficiency, and so that is why people go to
the trouble of using BeginReceive() / EndReceive() rather than just
creating a new thread for each connection.

If the above is correct, I would be interested in hearing what people
might know about the specific Framework / OS mechanisms that are used to
wait for input on a port without creating a separate thread.

Carl





*** Sent via Developersdex http://www.developersdex.com ***
.



Relevant Pages

  • Event Machine - callbacks from different connections
    ... "You can also call send_data to write to a connection other than the one ... whose callback you are calling send_data from. ... I want a packet of data to be sent out on port 1700 when a packet ... puts "Port = #" ...
    (comp.lang.ruby)
  • callback connections and firewall
    ... I try to get a corba application working between a server (no ... The application includes callback ... If server and client reside on the ... I read that JacORB in contrast to Sun's IDL keeps the connection from ...
    (comp.object.corba)
  • RE: Controls not updated by callback event
    ... In a client callback, a client script function sends a request to the ... Another function receives the result from the server code ... Microsoft Online Community Support ...
    (microsoft.public.dotnet.framework.aspnet.buildingcontrols)
  • Re: Intermittent Remoting Event Callback Problem
    ... MarshalByRefObj created using the New statement and returned to the client ... a SAO resulting in a callback to a "proxy"/wrapper class. ... to the server upon disconnection. ... reqMsg, IMessage retMsg) ...
    (microsoft.public.dotnet.distributed_apps)
  • Re: Fire wall or NAT router problem
    ... The problems start when your server wants to make a callback to your ... client, then a connection is created from the server to the client. ... the client has a desktop firewall which may block the callback ...
    (microsoft.public.dotnet.framework.remoting)