On Mon, 19 May 2008 20:58:31 -0700, Ryan Liu <rl**@powercati .comwrote:
Will TcpClient.GetSt ream().Read()/ReadByte() block until at least one
byte
of data can be read?
Assuming the socket is in blocking mode, yes. Otherwise, you could get an
exception equivalent to the WSAEWOULDBLOCK error.
In a Client/Server application, what does it mean at the end of stream/no
more data available? Client could send data once few seconds of
minutes. Is
there an "end" at all?
The stream you get from a TCP socket will only reach the end when the
connection is closed.
In a C/S application, if server side call BeginginRead() again in
EndRead()
to create a endless loop to get message from client, is this a better
approach than "one thread per client" approach?
Yes. And this is better on the client side too. Using the async API on
the network i/o classes (well, for sure the Socket class...I'm pretty sure
TcpClient, NetworkStream, etc. all follow) will implicitly use IOCP when
available (which is on any NT-based version of Windows), and IOCP is the
most scalable API to use with network i/o.
I personally find the async API more convenient and easier to understand,
but then I'm odd that way. :) YMMV.
I understand aync read/write will put job into query and later it uses
system thread pool to execute it. The question is when will it be
executed?
Wait until hardware available or plus waiting thread available? If there
are
too many clients, will this async approach cause too much delay and
client
can not get expected response from server in timely manner? And this can
avoid by "one thread per client" mode?
As I wrote above, IOCP is the most scalable approach, and that's what the
async API uses. It works by having a pool of threads waiting on i/o
completions. One thread can handle i/o completions for any number of
sockets. This means that as i/o completions are queued by the OS, the
same thread can just keep pulling the completions off the queue and
processing them, avoiding a thread context switch just to process a
different socket.
As for when the thread will get to run, it will mostly run according to
the usual Windows scheduling mechanism. The IOCP threads all sit and wait
on a queue. As soon as something's in the queue, the threads become
runnable. They are scheduled according to the normal round-robin
rotation, so once the first runnable IOCP thread gets to run, it dequeues
the completion and processes it. If there are still i/o completions in
the queue, that one thread will keep dequeuing them. If another CPU core
becomes available and a second IOCP thread reaches the head of the line in
the round-robin scheme, then that second thread will dequeue an i/o
completion and process it.
Each IOCP thread, once it gets a chance to run, will not yield until
either the queue is empty or it's pre-empted. In this way, the threads
are assured of consuming their entire thread quantum as long as there's
actually work to be done.
Finally, Windows knows that IOCP is special and actually does manage
thread scheduling and some other things to help ensure that the CPUs are
used most efficiently with IOCP. For example, if I recall correctly the
Windows scheduler won't switch to another IOCP thread just because one
IOCP thread is done with its quantum. It's smart enough that, once an
IOCP thread gets to run, that thread will keep running through multiple
quantums as long as there aren't non-IOCP threads that are runnable.
Again, this minimizes context switching.
Pete