tags:

views:

946

answers:

5

I'm working on an instant messenger client in C++ (Win32) and I'm experimenting with different asynchronous socket models. So far I've been using WSAAsyncSelect for receiving notifications via my main window. However, I've been experiencing some unexpected results with Winsock spawning additionally 5-6 threads (in addition to the initial thread created when calling WSAAsyncSelect) for one single socket.

I have plans to revamp the client to support additional protocols via DLL:s, and I'm afraid that my current solution won't be suitable based on my experiences with WSAAsyncSelect in addition to me being negative towards mixing network with UI code (in the message loop).

I'm looking for advice on what a suitable asynchronous socket model could be for a multi-protocol IM client which needs to be able to handle roughly 10-20+ connections (depending on amount of protocols and protocol design etc.), while not using an excessive amount of threads -- I am very interested in performance and keeping the resource usage down.

I've been looking on IO Completion Ports, but from what I've gathered, it seems overkill. I'd very much appreciate some input on what a suitable socket solution could be!

Thanks in advance! :-)

+2  A: 

consider to use the ASIO library you can find in boost (www.boost.org).

Gaetano Mendola
+1  A: 

In some ways IO Completion Ports (IOCP) are overkill but to be honest I find the model for asynchronous sockets easier to use than the alternatives (select, non-blocking sockets, Overlapped IO, etc.).

The IOCP API could be clearer but once you get past it it's actually easier to use I think. Back when, the biggest obstacle was platform support (it needed an NT based OS -- i.e., Windows 9x did not support IOCP). With that restriction long gone, I'd consider it.

dpp
+4  A: 

There are four basic ways to handle multiple concurrent sockets.

  1. Multiplexing, that is using select() to poll the sockets.
  2. AsyncSelect which is basically what you're doing with WSAAsyncSelect.
  3. Worker Threads, creating a single thread for each connection.
  4. IO Completion Ports, or IOCP. dp mentions them above, but basically they are an OS specific way to handle asynchronous I/O, which has very good performance, but it is a little more confusing.

Which you choose often depends on where you plan to go. If you plan to port the application to other platforms, you may want to choose #1 or #3, since select is not terribly different from other models used on other OS's, and most other OS's also have the concept of threads (though they may operate differently). IOCP is typically windows specific (although Linux now has some async I/O functions as well).

If your app is Windows only, then you basically want to choose the best model for what you're doing. This would likely be either #3 or #4. #4 is the most efficient, as it calls back into your application (similar, but with better peformance and fewer issues to WSAsyncSelect).

The big thing you have to deal with when using threads (either IOCP or WorkerThreads) is marshaling the data back to a thread that can update the UI, since you can't call UI functions on worker threads. Ultimately, this will involve some messaging back and forth in most cases.

If you were developing this in Managed code, i'd tell you to look at Jeffrey Richter's AysncEnumerator, but you've chose C++ which has it's pros and cons. Lots of people have written various network libraries for C++, maybe you should spend some time researching some of them.

Mystere Man
#Jeffrey Richter's AysncEnumerator# wow!!!
divinci
+1  A: 

Just use synchronous models. Modern operating systems handle multiple threads quite well. Async IO is really needed in rare situations, mosty on servers.

stepancheg
+1  A: 

If you do decide to use IOCP (which, IMHO, is the best option if you're writing for Windows) then I've got some free code available which takes away a lot of the work that you need to do.

Ltest version of the code and links to the original articles are available from here.

And my views on how my framework compares to Boost::ASIO can be found here: http://www.lenholgate.com/archives/000810.html.

Len Holgate
Very helpful articles. Thank you very much.
kraf
Oh, one thing that I didn't mention; the issue of marshalling from the IOCP thread to the GUI thread is helped (in my framework) by the fact that both the socket wrapper objects and the buffer objects are reference counted; simply AddRef() them and post them as params in a windows message...
Len Holgate