PC Review


Reply
Thread Tools Rate Thread

Socket.BeginReceive/Socket.EndReceive Documentation Problem

 
 
Cool Guy
Guest
Posts: n/a
 
      24th May 2005
In the documentation for both Socket.BeginReceive and Socket.EndReceive, it
is stated that receiving/sending will be happen in a separate thread.

However, from looking at the code in Reflector, you can see that this
simply isn't true. Instead they just use WSARecv and WSASend,
respectively.

WTF?
 
Reply With Quote
 
 
 
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      24th May 2005

"Cool Guy" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> In the documentation for both Socket.BeginReceive and Socket.EndReceive,
> it
> is stated that receiving/sending will be happen in a separate thread.
>
> However, from looking at the code in Reflector, you can see that this
> simply isn't true. Instead they just use WSARecv and WSASend,
> respectively.
>
> WTF?


Yes, and what? The are called on the same IOCP pool thread.

Willy.



 
Reply With Quote
 
Cool Guy
Guest
Posts: n/a
 
      24th May 2005
"Willy Denoyette [MVP]" <(E-Mail Removed)> wrote:

> Yes, and what? The are called on the same IOCP pool thread.


Huh? Are you saying that the documentation is correct?

I was under the impression that WSASend/Recv run on the same thread as the
one on which they're called.
 
Reply With Quote
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      24th May 2005
Yes, BeginReceive is on the caller's thread, EndReceive is on a thread pool
thread (more specificaly on a IOCP thread).
The same goes for BeginSend/EndSend, both are on a separate thread.

After calling BeginSend the thread can simply continue with other things,
while the IOCP thread is blocked on the EndReceive waiting for data to come
in, this is the foundation for all asynchronous IO in .NET.
Note that it's mandatory to pair each BeginXXX with a EndXXXX.


Willy.


"Willy Denoyette [MVP]" <(E-Mail Removed)> wrote in message
news:Ocj2%(E-Mail Removed)...
>
> "Cool Guy" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> In the documentation for both Socket.BeginReceive and Socket.EndReceive,
>> it
>> is stated that receiving/sending will be happen in a separate thread.
>>
>> However, from looking at the code in Reflector, you can see that this
>> simply isn't true. Instead they just use WSARecv and WSASend,
>> respectively.
>>
>> WTF?

>
> Yes, and what? The are called on the same IOCP pool thread.
>
> Willy.
>
>
>



 
Reply With Quote
 
Carl Gunther via DotNetMonster.com
Guest
Posts: n/a
 
      8th Jun 2005
I am new to this topic, and happened upon this thread while trying to make
sense of the MSDN sample code at:

ms- help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/cpguide/html/cpconNon-
blockingServerSocketExample.htm

(a VB version of this is available online at:
http://msdn2.microsoft.com/library/fx6588te(en- us,vs.80).aspx)

My question is really about that sample, but first, let me state my
understanding of what you are saying, so you can let me know whether I have
it right:

You are saying that BeginReceive is "on the caller's thread." Certainly, it
is invoked from the caller's thread (which perhaps is what you mean).
However, the documentation clearly states that "When your application calls
BeginReceive, the system will use a separate thread to execute the
specified callback method, and will block on EndReceive until the Socket
reads data or throws an exception." So, according to the documentation, the
*callback* method does *not* execute on the caller's thread, but rather on
a thread that is spawned by the BeginReceive method.

Now, when EndReceive is invoked, it "blocks" until at least some data has
been received by the client. I assume that means that if any data has been
received at all, even a single character, it will "release," returning that
data.

So, when you say that EndReceive is "on a thread pool thread," I'm guessing
that you mean the thread that was allocated when BeginReceive was called;
the same thread on which the callback function that invoked EndReceive is
running. Which means that EndReceive does not allocate any new thread of
its own; it is a synchronous function (so far as its caller is concerned)
that waits for input from the client, and returns as soon as any has been
received.

Apologies for the length of the preceding; hopefully all of the above is
correct. Assuming that it is, on to my question about the sample code:

Given that the initial BeginReceive operation spawns a new thread on which
ReadCallBack runs, why is it necessary for ReadCallBack to invoke
BeginReceive *again*, spawning yet another thread, just to pick up the next
portion of the input from the client (which could happen an indefinite
number of times)? Why not have a Socket function that can perform a
*synchronous* read from the client (i.e., Socket.Receive()), and invoke
that function within a loop to pick up the rest of the input? The main
thread will not be blocked, as it has already spawned a worker thread when
it called the BeginAccept function.

Now, I know that the documentation for Socket.Receive says that "The
Receive method will only read data that arrives from the remote host
established in the Connect or Accept method." So, does that mean it will
*not* read data from a host established in the *BeginAccept* method?
Because I don't see why you couldn't mix an asynchronously-spawned
connection (e.g., BeginAccept / EndAccept) with synchronously performed
reading (e.g., Receive).

Creating a new thread for each little fragment of input seems unnecessarily
expensive, given that each invocation of the ReadCallBack delegate is just
exiting after it calls BeginReceive.

Thanks in advance for any insights you might provide.

Carl

Willy Denoyette [MVP] wrote:
>Yes, BeginReceive is on the caller's thread, EndReceive is on a thread pool
>thread (more specificaly on a IOCP thread).
>The same goes for BeginSend/EndSend, both are on a separate thread.
>
>After calling BeginSend the thread can simply continue with other things,
>while the IOCP thread is blocked on the EndReceive waiting for data to come
>in, this is the foundation for all asynchronous IO in .NET.
>Note that it's mandatory to pair each BeginXXX with a EndXXXX.
>
>Willy.
>
>>> In the documentation for both Socket.BeginReceive and Socket.EndReceive,
>>> it

>[quoted text clipped - 9 lines]
>>
>> Willy.

>



Willy Denoyette [MVP] wrote:
>Yes, BeginReceive is on the caller's thread, EndReceive is on a thread pool
>thread (more specificaly on a IOCP thread).
>The same goes for BeginSend/EndSend, both are on a separate thread.
>
>After calling BeginSend the thread can simply continue with other things,
>while the IOCP thread is blocked on the EndReceive waiting for data to come
>in, this is the foundation for all asynchronous IO in .NET.
>Note that it's mandatory to pair each BeginXXX with a EndXXXX.
>
>Willy.
>
>>> In the documentation for both Socket.BeginReceive and Socket.EndReceive,
>>> it

>[quoted text clipped - 9 lines]
>>
>> Willy.

>


--
Message posted via http://www.dotnetmonster.com
 
Reply With Quote
 
Carl Gunther via DotNetMonster.com
Guest
Posts: n/a
 
      12th Jun 2005
OK, I have figured out the nuances of this and am posting again in case
others are trying to figure this out themselves.

When you use BeginRead(), 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. Clearly the requirements
for saving state 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 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 EndRead(), processing it, calling BeginRead() again if
there is more input, and then terminating. When your callback completes,
the thread is returned to the thread pool.

This means that you are tying up a thread only during the time that your
callback is running. While you are waiting for client input, 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 to think it up and type it. Then, we
will have one one-hundreth of the threads running using the BeginRead() /
EndRead() 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 BeginRead() / EndRead() rather than just creating a new
thread for each connection.

Carl Gunther wrote:
>I am new to this topic, and happened upon this thread while trying to make
>sense of the MSDN sample code at:
>
>ms- help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/cpguide/html/cpconNon-
>blockingServerSocketExample.htm
>
>(a VB version of this is available online at:
>http://msdn2.microsoft.com/library/fx6588te(en- us,vs.80).aspx)
>
>My question is really about that sample, but first, let me state my
>understanding of what you are saying, so you can let me know whether I have
>it right:
>
>You are saying that BeginReceive is "on the caller's thread." Certainly, it
>is invoked from the caller's thread (which perhaps is what you mean).
>However, the documentation clearly states that "When your application calls
>BeginReceive, the system will use a separate thread to execute the
>specified callback method, and will block on EndReceive until the Socket
>reads data or throws an exception." So, according to the documentation, the
>*callback* method does *not* execute on the caller's thread, but rather on
>a thread that is spawned by the BeginReceive method.
>
>Now, when EndReceive is invoked, it "blocks" until at least some data has
>been received by the client. I assume that means that if any data has been
>received at all, even a single character, it will "release," returning that
>data.
>
>So, when you say that EndReceive is "on a thread pool thread," I'm guessing
>that you mean the thread that was allocated when BeginReceive was called;
>the same thread on which the callback function that invoked EndReceive is
>running. Which means that EndReceive does not allocate any new thread of
>its own; it is a synchronous function (so far as its caller is concerned)
>that waits for input from the client, and returns as soon as any has been
>received.
>
>Apologies for the length of the preceding; hopefully all of the above is
>correct. Assuming that it is, on to my question about the sample code:
>
>Given that the initial BeginReceive operation spawns a new thread on which
>ReadCallBack runs, why is it necessary for ReadCallBack to invoke
>BeginReceive *again*, spawning yet another thread, just to pick up the next
>portion of the input from the client (which could happen an indefinite
>number of times)? Why not have a Socket function that can perform a
>*synchronous* read from the client (i.e., Socket.Receive()), and invoke
>that function within a loop to pick up the rest of the input? The main
>thread will not be blocked, as it has already spawned a worker thread when
>it called the BeginAccept function.
>
>Now, I know that the documentation for Socket.Receive says that "The
>Receive method will only read data that arrives from the remote host
>established in the Connect or Accept method." So, does that mean it will
>*not* read data from a host established in the *BeginAccept* method?
>Because I don't see why you couldn't mix an asynchronously-spawned
>connection (e.g., BeginAccept / EndAccept) with synchronously performed
>reading (e.g., Receive).
>
>Creating a new thread for each little fragment of input seems unnecessarily
>expensive, given that each invocation of the ReadCallBack delegate is just
>exiting after it calls BeginReceive.
>
>Thanks in advance for any insights you might provide.
>
>Carl
>
>>Yes, BeginReceive is on the caller's thread, EndReceive is on a thread pool
>>thread (more specificaly on a IOCP thread).

>[quoted text clipped - 12 lines]
>>>
>>> Willy.

>
>>Yes, BeginReceive is on the caller's thread, EndReceive is on a thread pool
>>thread (more specificaly on a IOCP thread).

>[quoted text clipped - 12 lines]
>>>
>>> Willy.

>


--
Message posted via DotNetMonster.com
http://www.dotnetmonster.com/Uwe/For...users/200506/1
 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Problem with Socket.EndReceive Returning Invalid Value O.B. Microsoft C# .NET 2 28th Sep 2007 01:18 AM
Socket.BeginReceive problem =?Utf-8?B?Q2VjaWwgU2hlbmc=?= Microsoft Dot NET Framework 2 6th Nov 2006 09:11 AM
Need help - Socket EndReceive & BeginReceive Marty Microsoft VB .NET 1 3rd Nov 2004 04:11 PM
Socket.Receive and BeginReceive Problem Shoveler Microsoft VB .NET 0 18th May 2004 08:13 PM
Socket.BeginReceive() Problem =?Utf-8?B?SiBCcmFk?= Microsoft C# .NET 0 23rd Apr 2004 03:31 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 04:56 PM.