|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Waiting for incoming data on multiple socketsUsing the System.Net.Sockets.Socket class, how am I supposed to wait for incoming data? If, for example, I've got a large number of connections that all need to be monitored for incoming data, do I have to call BeginReceive() for each socket (possibly producing 50 background threads assuming a naive socket implementation) and then spawn another 50 threads myself for blocking on the EndReceive() methods of all the sockets? Back in C++ I had a shared monitoring thread which blocked by calling WaitForMultipleObjects() on an array of all the sockets. I think I could reimplement this concept in .NET using the WaitHandles provided by the AsyncResult class that is returned from Socket.BeginReceive(). Is that the way to go? Thanks, -Markus- Markus Ewald <Markus_Ew***@gmx.net> wrote:
> Using the System.Net.Sockets.Socket class, how am I supposed to wait for The socket implementation is not naive in that way, it uses asynchronous> incoming data? > > If, for example, I've got a large number of connections that all need to > be monitored for incoming data, do I have to call BeginReceive() for > each socket (possibly producing 50 background threads assuming a naive > socket implementation) I/O instead. > and then spawn another 50 threads myself for I personally find it much easier to pass a callback to the BeginReceive> blocking on the EndReceive() methods of all the sockets? method. That way, a thread will be allocated from the threadpool only when some data arrives. > Back in C++ I had a shared monitoring thread which blocked by calling That sounds like a Windows-ism for the BSD select() call. You can do> WaitForMultipleObjects() on an array of all the sockets. that via Socket.Select, if you wish - it won't be as performant as the callback, though, and you have a potential socket starvation problem for sockets towards the end of the array. > I think I could reimplement this concept in .NET using the WaitHandles I wouldn't recommend it, no. In C# 2.0 I'd use anonymous delegates to> provided by the AsyncResult class that is returned from > Socket.BeginReceive(). Is that the way to go? simulate continuation passing style code, passing the anonymous delegate as the callback to the BeginReceive method. -- Barry "Markus Ewald" <Markus_Ew***@gmx.net> wrote Call BeginReceive on all 50 sockets, and pass in a callback function. For > If, for example, I've got a large number of connections that all need to > be monitored for incoming data, do I have to call BeginReceive() for each > socket (possibly producing 50 background threads assuming a naive socket > implementation) and then spawn another 50 threads myself for blocking on > the EndReceive() methods of all the sockets? good luck, pass in the actual socket as state. When your callback hits, call EndReceive, pull out the data, and proceed. For more details on this than you ever wanted: http://makeashorterlink.com/?R2EE5246D Chris Mullins wrote:
> "Markus Ewald" <Markus_Ew***@gmx.net> wrote Thanks Barry and Chris, sounds like the callback is the way to go.>> If, for example, I've got a large number of connections that all need to >> be monitored for incoming data, do I have to call BeginReceive() for each >> socket (possibly producing 50 background threads assuming a naive socket >> implementation) and then spawn another 50 threads myself for blocking on >> the EndReceive() methods of all the sockets? > > Call BeginReceive on all 50 sockets, and pass in a callback function. For > good luck, pass in the actual socket as state. > > When your callback hits, call EndReceive, pull out the data, and proceed. > Just to sum it up: - Call BeginReceive() on all the sockets, passing a callback function to handle incoming data - Do *not* call EndReceive() in the callback function so that it will be triggered again when new data arrives (?) - When the application needs to terminate, call Close() on each socket and skip the EndReceive() call. I think the MSDN documentation on this is rather scarce. What if, for example, new data arrives while my callback is executing? Will the callback be entered again immediately after it finishes? -Markus- Markus Ewald <Markus_Ew***@gmx.net> wrote:
> - Call BeginReceive() on all the sockets, passing a callback function to No, you DO call EndReceive() in the callback. You must, in general for> handle incoming data > - Do *not* call EndReceive() in the callback function so that it will be > triggered again when new data arrives (?) any Begin*/End* pair, in order to get any return value or out parameters, and in order to free resources associated with the IAsyncResult. You call BeginReceive() again in the callback once you're done processing / queuing for processing the data you've just received. > - When the application needs to terminate, call Close() on each socket You should call Shutdown() and close both sides of the connection> and skip the EndReceive() call. instead. You can safely call Shutdown() on any thread, as long as the socket isn't closed. That will cause the Receive() to receive 0 bytes, which is part of the normal clean TCP shutdown sequence. You should call Close() in a thread that logically owns the socket, or at the very least in a thread which isn't logically blocking on the socket (I'm including a pending callback from a Begin* call as "logically blocking"). So, typically, you'll call Close() on the socket in the callback when you receive 0 bytes. > I think the MSDN documentation on this is rather scarce. What if, for You need to play with it, to get a feel for how it works. I advise> example, new data arrives while my callback is executing? Will the > callback be entered again immediately after it finishes? writing a test application pair with socket server & client, in order to get a feel for how it all works. You may need to develop some abstractions to get it all to work together nicely, I know I did. Coordinating clean shutdowns and handling exceptions gracefully are probably the two harder parts of asynchronous socket programming, IMHO, once you've gotten your head around the continuation-passing-style nature of callback-based .NET async. -- Barry |
|||||||||||||||||||||||