views:

530

answers:

3

Here is where I am at presently. I am designing a card game with the aim of utilizing major components for future work. The part that is hanging me up is creating a layer of abstraction between the server and the client(s). A server is started, and then one or more clients can connect (locally or remotely). I am designing a thick client but my friend is looking at doing a web-based client. I would like to design the server in a manner that allows a variety of different clients to call a common set of server commands.

So, for a start, I would like to create a 'server' which manages the game rules and player interactions, and a 'client' on the local CLI (I'm running Ubuntu Linux for convenience). I'm attempting to flesh out how the two pieces are supposed to interact, without mandating that future clients be CLI-based or on the local machine.

I've found the following two questions which are beneficial, but don't quite answer the above.

I don't require anything full-featured right away; I just want to establish the basic mechanisms for abstraction so that the resulting mock-up code reflects the relationship appropriately: there are different assumptions at play with a client/server relationship than with an all-in-one application.

Where do I start? What resources do you recommend?

Disclaimers: I am familiar with code in a variety of languages and general programming/logic concepts, but have little real experience writing substantial amounts of code. This pet project is an attempt at rectifying this.

Also, I know the information is out there already, but I have the strong impression that I am missing the forest for the trees.

+2  A: 

Read up on RESTful architectures.

Your fat client can use REST. It will use urllib2 to make RESTful requests of a server. It can exchange data in JSON notation.

A web client can use REST. It can make simple browser HTTP requests or a Javascript component can make more sophisticated REST requests using JSON.

Your server can be built as a simple WSGI application using any simple WSGI components. You have nice ones in the standard library, or you can use Werkzeug. Your server simply accepts REST requests and makes REST responses. Your server can work in HTML (for a browser) or JSON (for a fat client or Javascript client.)

S.Lott
the 'Stateless' requirement concerns me; it would seem that a game application would require significant overhead with each request if the server retains no client context.
hewhocutsdown
The protocol is stateless. Each message is completely independent. Web servers, maintain sessions via REST all the time. The server can be stateful; the messages, however, are independent (stateless). There's no sequence numbering or "HELO, DOTHIS, BYE" sequence of messages.
S.Lott
I'll repeat back what I think you're saying:The web server may store information regarding the game and players, and the clients may do the same. But statelessness applies to the communications between the two. A PUT request has no requirements before or after itself; it is self-sufficient, in a sense.On a related note, then, does this infer that the application is purely client-driven, as per Alex Martelli's recommendation?
hewhocutsdown
@hewhocutsdown: Correct: each request (GET, POST, PUT, DELETE) is self-sufficient ("stateless"). The application will -- generally -- be client-driven. The server may have to reject (with a 404 status) requests that are inappropriate for the current game state. In a sense the URI's come and go based on the state of the game/server.
S.Lott
+2  A: 

I would consider basing all server / client interactions on HTTP -- probably with JSON payloads. This doesn't directly allow server-initiated interactions ("server push"), but the (newish but already traditional;-) workaround for that is AJAX-y (even though the X makes little sense as I suggest JSON payloads, not XML ones;-) -- the client initiates an async request (via a separate thread or otherwise) to a special URL on the server, and the server responds to those requests to (in practice) do "pushes". From what you say it looks like the limitations of this approach might not be a problem.

The key advantage of specifying the interactions in such terms is that they're entirely independent from the programming language -- so the web-based client in Javascript will be just as doable as your CLI one in Python, etc etc. Of course, the server can live on localhost as a special case, but there is no constraint for that as the HTTP URLs can specify whatever host is running the server; etc, etc.

Alex Martelli
what do you see the key limitations to be in the async client initiation approach described above?
hewhocutsdown
+2  A: 

First of all, regardless of the locality or type of the client, you will be communicating through an established message-based interface. All clients will be operating based on a common set of requests and responses, and the server will handle and reject these based on their validity according to game state. Whether you are dealing with local clients on the same machine or remote clients via HTTP does not matter whatsoever from an abstraction standpoint, as they will all be communicating through the same set of requests/responses.

What this comes down to is your protocol. Your protocol should be a well-defined and technically sound language between client and server that will allow clients to a) participate effectively, and b) participate fairly. This protocol should define what messages ('moves') a client can do, and when, and how the server will react.

Your protocol should be fully fleshed out and documented before you even start on game logic - the two are intrinsically connected and you will save a lot of wasted time and effort by competely defining your protocol first.

You protocol is the abstraction between client and server and it will also serve as the design document and programming guide for both.

Protocol design is all about state, state transitions, and validation. Game servers usually have a set of fairly common, generic states for each game instance e.g. initialization, lobby, gameplay, pause, recap, close game, etc...

Each one of these states has important state data related with it. For example, a 'lobby' state on the server-side might contain the known state of each player...how long since the last message or ping, what the player is doing (selecting an avatar, switching settings, going to the fridge, etc.). Organizing and managing state and substate data in code is important.

Managing these states, and the associated data requirements for each is a process that should be exquisitely planned out as they are directly related to volume of work and project complexity - this is very important and also great practice if you are using this project to step up into larger things.

Also, you must keep in mind that if you have a game, and you let people play, people will cheat. It's a fact of life. In order to minimize this, you must carefully design your protocol and state management to only ever allow valid state transitions. Never trust a single client packet.

For every permutation of client/server state, you must enforce a limited set of valid game messages, and you must be very careful in what you allow players to do, and when you allow them to do it.

Project complexity is generally exponential and not linear - client/server game programming is usually a good/painful way to learn this. Great question. Hope this helps, and good luck!

jscharf
I suspect it will be both good and painful. :)S. Lott above talks about RESTful web services; is this what you mean by protocol or are you meaning something more specific?
hewhocutsdown
I mean more specific. The protocol between your clients and server itself. What are the messages your clients send to the server? What does your server send back? How does a client flip a card? What if they send a 'flip-card' packet out of turn...what if the client sends to you 'I am flipping 52 cards'?Communicating via HTTP, sockets, bicycles, pigeon carriers, etc. is secondary - it's vehicular.Your main priority is how your client and server interact, and the relationship between them. Please feel free to email if you need clarification, I am glad to help :-)
jscharf