Sign in to follow this  
RWThurman

Async TCP/IP with a Console App

Recommended Posts

Background: I'm writing a game server that could handle over 1000 users. Unfortunatly, my current socket implementation is using blocking sockets with threads (as a quick hack). When I start to stress test my server, things get really gross (as expected). Question: Is it possible to use async TCP/IP with a console app, or do I need to create a real Windows window and use their event model?

Share this post


Link to post
Share on other sites
I don't understand what you mean by network thread.

I'm thinking I have to switch over to the windows event pump because, the winsock async network calls want a window handle for returning events to me.

Share this post


Link to post
Share on other sites
Asyncronous is usable on a Windows application only.

In a console app you would have to look into non-blocking sockets.

People often get confused with non-blocking and asyncronous. They are greatly different.

Async uses windows messages to get the job done allowing you to free up CPU time.

Non-blocking loops continuously boosting your CPU usage to 100%.

Share this post


Link to post
Share on other sites
In a console application you can use non-blocking sockets.

What exactly "async" is depends on your point of view. WSAAsyncSelect should, in my opinion, never be used for anything as it involves USER32.DLL in a wholly non-user-interface operation. Windows user interface messages are designed for users clicking things, which is not what you want. It's basically a hack which was designed for win16 cooperative multitasking.

You can quite adequately use as many sockets in non-blocking mode as you like, in a console app without requiring WSAAsyncSelect, however, you will need to use some other platform-specific synchronisation mechanism instead.

I believe that on win32 the mechanism you need to use is called "I/O completion ports", which will allow you to create an event which is triggered by some specified activity, you can block on that event then find out what happened. I don't know the details.

Of course select() is still a simple option with many examples, but it has the following problems:
- Very inefficient on large (1000s) numbers of sockets (every time a single thing happens, you have to scan and repopulate an array-like structure)
- You can't wait for a socket event *OR* something else (Except a timeout) easily in win32 with select (On Unix you can)

Non-blocking loops do *NOT* boost your CPU time to 100% unless you use busy-waiting, which I don't recommend. Note that a non-blocking loop might be a sensible implementation for a game client which is looping on some timer doing game logic and rendering etc as well, but probably isn't for a game server.

Mark

Share this post


Link to post
Share on other sites
Thanks MarkR!

I had explored all the other options except I/O Completion Ports. You're right, glomming async ports into the windows event spiggot seemed like a huge hack to me as well.

Lonewolff, I had looked seriously into non-blocking ports via select. Even though everyone said it was a step up from threaded blocking call, it was still very lame when you have a lot of connections. Hey, even if I were to poll, I definately would have shoved a sleep(0) call in there somewhere.

I did find a asynch class last night that didn't involve MFC, but when I started to try to get it to compile, I noticed it had a thread lurking in its members. One thread per socket was a step backwards even if it was async. I sort of threw up my hands and went to sleep.

I'll try these I/O Completion Ports next. I founds a nice looking link here.
http://www.microsoft.com/technet/sysinternals/information/IoCompletionPorts.mspx

Share this post


Link to post
Share on other sites
Why not use WSAEventSelect??? Works similar to WSAAsyncSelect, but does not require a window msg queue, instead it triggers kernel event objects. I use it in a console app, works quite nicely, alot easier to use IMHO than IO-completion ports.

Share this post


Link to post
Share on other sites
I'm trying to figure the difference between I/O Completion ports and WSAEventSelect.

I'm beginning to think that WSAEventSelect is a single threaded version of I/O Completion Ports. Is this right?

Edit: I found a really great article on overlapped I/O with worker threads here: http://www.codeproject.com/internet/SimpleIOCPApp.asp

[Edited by - RWThurman on March 8, 2007 1:56:17 PM]

Share this post


Link to post
Share on other sites
I/O-completion ports and WSAEventSelect are different animals. IOCP also allows the use of an internal thread pool. So esentially u ask it to run your function and it figures out the threading issues, its actually a bit more complicated than that but that is the jist. According to M$ IOCP is the only scalable solution for large amounts of connecting users, but somehow i doubt that considering alot of high end apps, that run on windows, (such as Apache) dont, as far as i know, use them.

I use WSAEventSlect with around 50 connections, but i make sure to multiplex multiple connections on only a few threads. I might look at how Apache does this for 1000s of connections.

Share this post


Link to post
Share on other sites
Asynchronous sockets are not high performance, and I believe there is a limitation of 63 sockets max in the async select code (related to the NT kernel 64-object limitation for WaitForMultipleObjects, I believe).

Your options include non-blocking sockets, or select(), or using I/O completion ports.

Share this post


Link to post
Share on other sites
Thanks for all the sage advice. I'll be going with I/O completion.

The article I mentioned above seems to make I/O completion as easy as it possibly can.

Share this post


Link to post
Share on other sites
Quote:
Original post by RWThurman
Background:
I'm writing a game server that could handle over 1000 users. Unfortunatly, my current socket implementation is using blocking sockets with threads (as a quick hack). When I start to stress test my server, things get really gross (as expected).

Question:
Is it possible to use async TCP/IP with a console app, or do I need to create a real Windows window and use their event model?



With non-blocking and a tight input loop (using the console routine that tests if a key was hit). It depends how extensive the input needs to be for the control inteface on the console App -- if you can limit it to single char driven menus its fairly simple -- no long waiting at a prompt to get input tgat would stall the network processing. Switch() driven FSM if its a multi-tiered menu. As someone else mentioned you could also have a network thread which is a little more complicated.

Share this post


Link to post
Share on other sites
Wow! I got the IO completion system up and running. I thought this whole thing was going to a big locking nightmare. In the end, I was able to avoid using any mutexs or spinlocks. I was able to replace the old system with the new async/overlapped system too.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this