Server Side Programming

Started by
10 comments, last by Rasterman 11 years, 9 months ago
Our game is going to have a turn based strategy battle system. Naturally, it would be really awesome to be able to battle your friends. So I am planning to write a Ruby on Rails server side program to coordinate connecting a player with a friend or random stranger for a single battle.

My goal is to keep the server load to a minimum, which means a few design decisions that make sense at the moment, but server stuff is a little new for me, so please feel free to tear holes in these decisions and/or enlighten me on issues I may have missed.

First off, it seems like a good idea to throttle down the frequency that the client side program checks the server for new information, say at most once per second.

Second, it seems like doing all battle calculations client side and then sending the results through the server to the other client would cut down the server load, and also simplify it so that I am not reproducing core C++ game logic in ruby on the server. This would probably work as follows, client A performs an attack that effects units 1 and 2 in the battle field, upload the attack name and the effects to the server. Client B checks the server and pulls the info, then simulates the attack, but in reality just applies the effects that client A uploaded. Rinse and repeat.

I like the simplicity of this process, but it seems fairly ripe for cheating. How easy would it be for the person controlling client A to fake the data sent to the server so that they actually do more damage than the game calculated (which would seem to get the two games out of sync and venture into undefined territory)? Is this really worth worrying about? The target will initially be iOS and Android, does this make it more difficult to cheat?

Are there any unknowns that I should be more worried about, like packet loss? I have a contingency plan to deal with people disconnecting, but there might be other things I haven't thought about.

I'm looking forward to hearing any thoughts.
Advertisement
First off, it seems like a good idea to throttle down the frequency that the client side program checks the server for new information, say at most once per second.
[/quote]

This is one of the reasons that web stacks, like RoR or PHP or whatever, are poor matches for game-style networking that requires interactive, "push" notifications. You should come see me talk at GDC Europe in August on this exact topic :-)

How easy would it be for the person controlling client A to fake the data sent to the server so that they actually do more damage than the game calculated[/quote]

Very easy. It's done all the time in games that have client-side authority and are popular enough that players care.
enum Bool { True, False, FileNotFound };

How easy would it be for the person controlling client A to fake the data sent to the server so that they actually do more damage than the game calculated


Very easy. It's done all the time in games that have client-side authority and are popular enough that players care.
[/quote]

There are even generic tools (CheatEngine for example) That simplify this process to the point that even amateurs with no programming knowledge can cheat in these games with relative ease, so the game doesn't even have to be popular to get hit by cheaters if you do this.
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

My goal is to keep the server load to a minimum, which means a few design decisions that make sense at the moment, but server stuff is a little new for me, so please feel free to tear holes in these decisions and/or enlighten me on issues I may have missed.



Second, it seems like doing all battle calculations client side and then sending the results through the server to the other client would cut down the server load, and also simplify it so that I am not reproducing core C++ game logic in ruby on the server. This would probably work as follows, client A performs an attack that effects units 1 and 2 in the battle field, upload the attack name and the effects to the server. Client B checks the server and pulls the info, then simulates the attack, but in reality just applies the effects that client A uploaded. Rinse and repeat.


Since this sounds like it's not a web-based game, I'd suggest developing/implementing much of the game logic in C++ on the server, and abandoning using HTTP and web scripting for this. Server-side may be new to you, and writing a multi-threaded server with game logic may be a difficult undertaking, but it achieves the best results. It's pretty fantastic the first time you connect to your own game server from a mobile device, or from any game client for that matter.

I have done some development on Android; for game lobbies and player authentication we send XML-based messages over a SSL/TLS layer to our own server; for turn-based we also use XML, and for live games we marshal game updates to/from the server in whatever binary format we want. We use Linux for our servers, and choose arbitrary ports for clients to connect to. In all cases the connections are live and interactive, unlike HTTP which requires you to present session data for each request and doesn't really give you simple bidirectional communication that is used in games.

As long as the server makes the important decisions and the client just sends the player's intentions and presents/displays/animates the results, you can limit or prevent cheating. If the client can be modified to make better decisions or precise calculations for the player to their benefit, then even in the best scenario, a player can "cheat". If the game is designed such that there is no perfect or precise decision for a modified client to make, then you can effectively prevent cheating.
But is this whole memory scanning (like CheatEngine) a real issue on mobile devices? It seems like these are a bit more locked down and more difficult to mess with, but maybe I am just being naive.

Assuming that the internal variables of the client side C++ program can not be modified while the program is running, and only the HTTP posts are being faked, could I do some sort of verification thing like this. Say Player A attacks one of Player B's units. Client A (presumably) calculates the damage correctly, but Player A fakes the HTTP post to say that he did more damage. Then Client A on it's next interaction with the server, double checks that the posted damage corresponds with its own internally calculated value. If the values differ, penalize Player A for cheating.

I guess this all assumes that Player A cannot modify the program state while it is running. Is this a fair assumption (at least for iOS and Android)? What are the holes in my argument?

I could see how the server side C++ program would create a more professional and cheat proof user experience, but it seems like it would magnify the server load by orders of magnitude.
Cell phones can be "rooted" and cheats installed, but those are so far less pervasive than PC cheats. You have to make a judgement call here.
The described mechanism for detecting cheating wouldn't work, because the person who fakes the HTTP post for one turn, can easily fake it for the next turn, too. In fact, player A doesn't need to be running your client at all; he could just be posting the right set of HTTP requests.
If you compare player A and player B, and they have different outcomes, you don't know which one is cheating, and which one isn't. Or maybe there's just a bug in the program -- you shouldn't ban players for your own bugs.

enum Bool { True, False, FileNotFound };

I could see how the server side C++ program would create a more professional and cheat proof user experience, but it seems like it would magnify the server load by orders of magnitude.


I don't see why you want to minimalise the server load so damn much when actually the compiled server program written with c++ for turn based simple battle game would run faster and with less memory than your ruby script + RoR interpereter + Apache. Another thing is that your http requests would be much larger than your tcp/udp packets would be, which would raise your bandwidth usage.

You would do a call like http://yourdomain.com/battle.rb?didmg=55

This http request would be:

GET /battle.rb?didmg=55 HTTP/1.1
Host: http://yourdomain.com

The response then again would be something like this:

HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Etag: "3f80f-1b6-3e1cb03b"
Accept-Ranges: none
Content-Length: 438
Connection: close
Content-Type: text/html; charset=UTF-8
receiveddmg=45


The most funny thing is that all of this could be two different packets

dd55 and rd55 which is 8 bytes instead of ton of data.
For some reason I was making the assumption that the flops coming from my game calculations would represent a significant server load, but when you put it into the context of running the Ruby stuff plus the reality that communication is going to be the real server load, it makes a lot more sense to try to limit the communication traffic. And if HTTP is a lot more verbose than setting up a socket, then it seems like a better idea to learn about some socket programming.

I am thinking about writing the client side program in Lua using Moai. Does anyone have any recommendations for the server side program? I am comfortable with C++, Python, and Lua. From some initial research, it looks like ZeroMQ comes highly recommended. My main concern with it is its LGPL license. It seems to be safe to dynamically link to it, and I know how to do this on Unix based systems, but I'm not so familiar with packaging and distribution procedure on Windows and mobile devices (this is probably not the best place to ask this, I know).

Does anyone else have any other recommendations for writing a scalable server side program?
I suggest you to write the server with c++ and use winsock or berkley sockets. Bjeez guide to network programming explains everything you basically need to know about socket programming and little bit of planning how to write the networking will make it scalable. Once you learn to use them you really do not need anything else, except writing way to handle the packets which those higher level networking libraries offer.

One thing i find funny about ZeroMQ is that they say their transport system is faster than TCP, but under it they say that the messages are also carried over TCP. Really fucked up marketing. inprof, IPC are inter process communication systems and multicast afaik means just sending the packet to many clients.
After some reading, it looks like for the most part, you are not allowed to do dynamic linking on iOS, so it looks like ZeroMQ is out. Any other suggestions for cross-platform scalable game servers? I would prefer to not reinvent the wheel with this.

This topic is closed to new replies.

Advertisement