How to write a lobby server

Hi guys,

So I’m writing a Chess matchmaking system based on a Lobby view with gaming rooms, general chat etc. So far I have a working prototype but I have big doubts regarding some things I did with the server. Writing a gaming 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 ordered “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 your opinions and see how you would handle some things so I can learn how to write a server correctly. 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 modification (eg. a player enters or exists the lobby) when iterating through it to dispatch an event without hurting throughput? Is ConcurrentHashMap the correct answer here, or are there some techniques I should know?

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. Thanks!

PS: Here’s a screenshot :


http://img232.imageshack.us/img232/9618/sansrezh.png

Uploaded with ImageShack.us

Well, I use a different thread for each new connecting client. Which, like you said, creates loads of Threads… I’m not sure if this is the best or most efficient way, but it is pretty simple.

I always have my clients send login/registration details in conjuction when they connect to the server. This of course can’t happen simultaneously, it’s just how I build my clients to prevent unknown clients from being connected for too long. Once I get their details I can identify the connection by name and I usually create a new separate thread to listen for messages of known clients (logged in clients) and leave the old thread to die.

What I would then do, is send a list of available games to the client that he can choose from, perhaps also automatically log him into a global chat room. After that, I’d just wait for the clients input and handle the input accordingly.

Bandwidth shouldn’t be a problem in a chess game, nor a lobby. The most heavy use of bandwidth would probably be a chat room where clients send String messages every time they want to say something (you can limit the amount of messages internally in the client, and also the server). If I’m worried by chat bandwidth I usually implement, in the client application, a queue. The client can send as many messages as he can type -> adding these messages to the queue -> from there the client application sends the message lowest in the queue every 5 seconds to the server. This should limit bandwidth usage pretty effectively in most cases.

The screenshot looks good. I’m not sure if you asked anything or if I answered anything but this is my input :P. Keep it up, as I said, looks good!

300 threads on the right OS is fine. On the wrong OS its dead in the water. So what you use is NIO or non blocking networking. Its not difficult and the api follows a C one that everyone was pointing to when asking why java didn’t have it. Some folks here hate it! However i have had no problems and i can control how many connections to have per thread which has made things very flexible and quite scalable. I switch back to plain sockets when i go to one connection per thread, but that is probably not needed.

Alternatively you could just make sure you don’t have a windows machine for the server and then even 1000 threads should be fine. It should also be noted that this is not 1000 threads all doing stuff but a 999 threads waiting for there turn on the networking “hardware”.

This is all assuming TCP. Which is what i would start with. Another approach i have used is the core protocol is UDP. Since its single packets flow control and lost packets are easy (ie timeout for a resend and no flow control). However i keep a message to the size of a single packet. For the “list of games” the client would then connect using a TCP for the bulk data. Since at any one time only a few are getting a full list the number of TCP connections to manage is much less. I also had a limit on the max number of TCP connections and just made clients que if there was too many.

+1 for NIO. Maybe try out Kryo?

If you don’t want to use NIO and want to limit the amount of threads, change one thread per client to one thread per request and set up a thread pool. You will have to close the connection to the client after sending a response, so the client has to poll for updates on the lobby.

Geh. That would give you pretty horrid delay if you have somewhat bad ping. I mean, three-way handshake + send + confirm + close + confirm. That’s lots of round trips.

JBoss Netty as NIO Framework is very nice too. Netty has some nice inbuilt stuff like HTTP Tunneling, WebSocket etc. This might be useful for using your server for HTML5 games…

What exactly are you refering to? I thought more like: accept connection, read data, process data, write response, close connection.

And after all it’s just a lobby…

To establish a TCP connection you need to do a 3 way handshake. That is done for you on the tcp/ip stack or implementation. But once your ping is in the 200ms, sending any data will take on the order of seconds.

(edit:) also receiving any data requires acks etc too. Tcp is not designed for high latency.

What? It sure is. The amount data that can be sent without confirmation increases all the time, so in theory as long as the connection is stable, it will work well. Sadly, there aren’t many stable 200 ms connections out there.

In practice high latency is poor on tcp even if stable. We have replaced it with our own UDP stuff for more than a 50% gain on some satellite connections with 200-400ms pings with less that 1% packet loss. In theory it is suppose to handle it, but the exact flow control behavior is up to the implementation, which are often sub optimal.

In this case you don’t have “time” for connection to adjust properly since the connection is closed as soon as its opened. In the case of open a connection each “query”.

But will it be any problem on a lobby server? IMHO not.