I am discussing with Voobly the idea of adding Chess to supported games. I have a working prototype (screenshot http://goo.gl/pYqM3) but I have big doubts regarding some things I did with the server. Writing a Voobly-like lobby server is a new programming experience to me and so I don't have a clear nor precise programming model for it. I also couldn't find a paper that describes how it should work. I asked Elusive (Voobly main developer) for some insight but appearantly he's busy for now. I bought "Java Network Programming 3rd edition" from Amazon and still waiting for shipment, hopefully I'll find some useful examples/information in this book.
Meanwhile, I'd like to gather opinions from the programmers here and see how they would handle some things so I can figure out how to write a well behaved server. Here are a few questions off the top of my head: (may be more will come)
First, let's define what a server does. It's primary functionality is to hold TCP connections with clients, listen to the events they generate and dispatch them to the other players. But is there more to it than that?
Should I use one thread per client? If so, 300 clients = 300 threads. Isn't that too much? What hardware is needed to support that? And how much bandwidth does a lobby consume then approx?
What kind of data structure should be used to hold the clients' sockets? How do you protect it from concurrent access when iterating through it to dispatch an event without hurting throughput?
When a user enters the lobby, what mechanism would you use to transfer the state of the lobby to him? And while this is happening, where do the other events bubble up?
A centralized lobby server's job is to relay information from other clients to each other AND to notify the client to changes/other events. A proper server doesn't *just* relay information, it generates its own (such as join/exit events, server notifications, etc etc).
If you want to code a server app. with less complications, use java, if you want speed (which is a top server priority), then use C or C++ (if using windows). Alternatively you can use C# if you're using windows, but thats not quite as fast as C/C++.
A thread per client is crazy talk. If you had 500 users and 500 threads, you would be consuming alot of unnecessary system resources, even for say, a dedicated server. You want you use thread pooling. This is the concept of using a handful of threads to handle many events. 10-15 threads is probably sufficient for a 300 user lobby of low-medium traffic. Alot of users will be idle, or taking time looking for a game, or simply chatting (which takes up much less thread time then consecutive game events). This means you don't need 1 thread per person ... To make this work, use global data structures to hold persistent user data, and have each thread in the pool constantly checking for network events. Upon detection, process the event and before you use any variable outside the local scope, invoke a thread synchronization function, such as critical sections, mutex or semaphores. You must do this for every variable accessed outside your local scope.
Be creative with your user data structure. Consider this example:
That is just a start. What actually goes in there is up to you and tends to be MUCH larger than that, minus your average, simple servers.
Finally... What I think you are getting at here is your network protocol. You have to have some sort of format for communicating between server and client. You can use anything from an XML-based protocol layer to a byte-based format (think PE File). To transmit the lobby state/info on join, you take all the information you have stored globally (such as game room title, max players per table, etc) and structure it as you wish, then send it off to the client. Some find it easier to use word-based protocols, but I find byte-order alot simpler and compact. Also with byte-based formats, you can pretty much just memcpy(); your relevant data structures right into a packet buffer, and the structure-order itself becomes the packet format. You can definitely find more on software-layer protocols on the internet (think RFC document releases).
I asked Elusive (Voobly main developer) for some insight but appearantly he's busy for now.
As they say, a magician never gives away his secrets. I'm not sure how he feels about open source, but he may be able to offer some advice (although he may feel otherwise).
Interesting endeavor you have here, good luck with it.
I am discussing with Voobly the idea of adding Chess to supported games. I have a working prototype (screenshot http://goo.gl/pYqM3) but I have big doubts regarding some things I did with the server. Writing a Voobly-like lobby server is a new programming experience to me and so I don't have a clear nor precise programming model for it. I also couldn't find a paper that describes how it should work. I asked Elusive (Voobly main developer) for some insight but appearantly he's busy for now. I bought "Java Network Programming 3rd edition" from Amazon and still waiting for shipment, hopefully I'll find some useful examples/information in this book.
Meanwhile, I'd like to gather opinions from the programmers here and see how they would handle some things so I can figure out how to write a well behaved server. Here are a few questions off the top of my head: (may be more will come)
First, let's define what a server does. It's primary functionality is to hold TCP connections with clients, listen to the events they generate and dispatch them to the other players. But is there more to it than that?
Should I use one thread per client? If so, 300 clients = 300 threads. Isn't that too much? What hardware is needed to support that? And how much bandwidth does a lobby consume then approx?
What kind of data structure should be used to hold the clients' sockets? How do you protect it from concurrent access when iterating through it to dispatch an event without hurting throughput?
When a user enters the lobby, what mechanism would you use to transfer the state of the lobby to him? And while this is happening, where do the other events bubble up?
Input is greatly appreciated.
A centralized lobby server's job is to relay information from other clients to each other AND to notify the client to changes/other events. A proper server doesn't *just* relay information, it generates its own (such as join/exit events, server notifications, etc etc).
If you want to code a server app. with less complications, use java, if you want speed (which is a top server priority), then use C or C++ (if using windows). Alternatively you can use C# if you're using windows, but thats not quite as fast as C/C++.
A thread per client is crazy talk. If you had 500 users and 500 threads, you would be consuming alot of unnecessary system resources, even for say, a dedicated server. You want you use thread pooling. This is the concept of using a handful of threads to handle many events. 10-15 threads is probably sufficient for a 300 user lobby of low-medium traffic. Alot of users will be idle, or taking time looking for a game, or simply chatting (which takes up much less thread time then consecutive game events). This means you don't need 1 thread per person ... To make this work, use global data structures to hold persistent user data, and have each thread in the pool constantly checking for network events. Upon detection, process the event and before you use any variable outside the local scope, invoke a thread synchronization function, such as critical sections, mutex or semaphores. You must do this for every variable accessed outside your local scope.
Be creative with your user data structure. Consider this example:
That is just a start. What actually goes in there is up to you and tends to be MUCH larger than that, minus your average, simple servers.
Finally... What I think you are getting at here is your network protocol. You have to have some sort of format for communicating between server and client. You can use anything from an XML-based protocol layer to a byte-based format (think PE File). To transmit the lobby state/info on join, you take all the information you have stored globally (such as game room title, max players per table, etc) and structure it as you wish, then send it off to the client. Some find it easier to use word-based protocols, but I find byte-order alot simpler and compact. Also with byte-based formats, you can pretty much just memcpy(); your relevant data structures right into a packet buffer, and the structure-order itself becomes the packet format. You can definitely find more on software-layer protocols on the internet (think RFC document releases).
Hope that answers your questions.
Mysterious_Blah
Edit for code box
As they say, a magician never gives away his secrets. I'm not sure how he feels about open source, but he may be able to offer some advice (although he may feel otherwise).
Interesting endeavor you have here, good luck with it.
If I was doing it I would use Boost Libs
Check them out here http://www.boost.org/
Here is a tutorial for you on Client/Server interaction hope that helps.
http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio.html
Note make it single-threaded for server apps ALWAYS.