Friday, November 13, 2015

networking - Is there a pattern for writing a turn-based server communicating with n clients over sockets?



I'm working on a generic game server that manages games for an arbitrary number of TCP socket-networked clients playing a game. I have a 'design' hacked together with duct-tape that is working, but seems both fragile and inflexible. Is there a well-established pattern for how to write client/server communication that is robust and flexible? (If not, how would you improve what I have below?)


Roughly I have this:



  • While setting up a game the server has one thread for each player socket handling synchronous requests from a client and responses from the server.

  • Once the game is going, however, all threads except for one sleep, and that thread cycles through all players one at a time communicating about their move (in reversed request-response).


Here's a diagram of what I have currently; click for larger/readable version, or 66kB PDF.


Sequence diagram of flow


Problems:




  • It requires players to respond exactly in turn with exactly the right message. (I suppose I could let each player respond with random crap and only move on once they give me a valid move.)

  • It does not allow players to talk to the server unless it's their turn. (I could have the server send them update about other players, but not process an asynchronous request.)


Final requirements:




  • Performance is not paramount. This will mostly be used for non-realtime games, and mostly for pitting AIs against each other, not twitchy humans.




  • The game play will always be turn-based (even if at a very high resolution). Each player always gets one move processed before all other players get a turn.





The implementation of the server happens to be in Ruby, if that makes a difference.



Answer



I'm not sure what it is exactly that you want to achieve. But, there's one pattern that is used constantly in game servers, and may help you. Use message queues.


To be more specific: when clients send messages to server, do not process them immediately. Rather, parse them and put into a queue for this specific client. Then, in some main loop (maybe even on another thread) go over all clients in turn, retrieve messages from the queue and process them. When processing indicates that this client's turn is finished, move on to the next.


This way, clients are not required to work strictly turn-by-turn; only fast enough so that you have something in the queue by the time client gets processed (you can, of course, either wait for the client or skip its turn if it lags). And you can add support for asynchronous requests by adding an "async" queue: when a client send a special request, it's added to this special queue; this queue is checked and processed more often then clients' ones.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...