Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 03 Jun 2003
Offline Last Active Today, 09:30 PM

#5298152 In depth articles about fast paced multiplayer network architecture

Posted by on 26 June 2016 - 04:25 PM

I'm not aware of any such comprehensive resources, unfortunately. Mainly, because all of the different solutions put together, make for the better part of a game engine, so where all the pieces exist together, they will make up an engine (Source or Unreal or whatever.)
And, the few resources that exist for game engines, typically do not put networking as their main illustration, because networking is only used by a subset of games, AND it's pretty complex (as you are finding!)

The meta-advice I can give is to separate concerns between different pieces of code. In Object Oriented code, this should be trying to achieve the "single responsibility principle." In a more functional approach, keeping each function shorter/smaller, and composing functions to achieve the end goal, would achieve the same results.

#5298133 20Hz Server Performance Dilemma

Posted by on 26 June 2016 - 01:17 PM

You don't need to use TCP just because "a request cannot be dropped."
Re-sending the request over UDP until you receive acknowledgement can be equally effective.
Just make sure that, if you stop receiving anything back from the server, you stop trying after a little bit, else you'll end up with a system that makes congestion worse once it happens.

I personally think the mini $5.00 VPS way is ideal here.

If your game depends on low latency, don't say I didn't warn you!

#5298132 Server/Client architecture for turn-based card game developed with Unity3D

Posted by on 26 June 2016 - 01:13 PM

If some client doesn't send some kind of request, the server can not change any data about the match.

There are two ways of soliving this, for turn-based games.

One is to have some "timeout clock" that knows about active games, and makes a web request that "the clock is ticking for game X" every so often.
This clock process needs to run more permanently than you can do with a simple PHP request handler, and you need some kind of management of when this process dies so it restarts.
You'd also need to tell it about games when they start, and when they stop.

The other is to say that the game only advances when at least one player wants it to advance. Then, make each player request updated state X times per minute/second.
Because at least one player makes requests, the game can advance. When both players close their browsers, or there is a network outage for your server, or whatever -- the game will simply be frozen!
This could be seen as a feature, somewhat depending on the specific rules and implementation of the game.

I understood that Redis allow me (like the most of nosql db) to store and write/read a lot faster than a SQL.

Yes, storing things in RAM without a guaranteed commit to disk is a lot faster! The draw-back is that, if you crash, well, you didn't have a guaranteed commit, so the data may be lost.
Thus, it's usually a good idea to keep permanent data (log of games played, user account information, etc) in a durable transactional store (such as most SQL databases.)
If your game pace is slow enough, that polling for the game state out of SQL does not add undue burden on the database infrastructure, you don't need to use a key/value store for that, at least while starting out.
If there's a single table "current_games" that contain a primary key of game ID and a value of "serialized game state" as JSON or binary data, then that's super easy to migrate out to a key/value store later.
The main thing you lose is the automatic purging of old data which comes from the TTL values on Redis keys.
To implement that, you can have a cron which runs every 10 minutes and deletes rows that have not been modified in the last day, or whatever the right value is for your game.

#5298042 20Hz Server Performance Dilemma

Posted by on 25 June 2016 - 05:17 PM

The messages themselves are not a lot.
However, $5 VPS slices are generally run on highly oversubscribed hosts, and generally have some pretty bad scheduling jitter.
Also, you will typically find them on ISPs that may promise you several terabytes of transfer per month free, but the actual achievable throughput might be something like 100 KB per second, which won't actually let you get to those amounts.

Speaking of Node, it's single threaded, so if you host on a multi-core box, you'll want to have multiple instances run in multiple separate processes. This means each of them needs to listen to a differetn port.

Finally, if you use Nginx for load balancing, you're kind-of stuck with HTTP; you can't do UDP over that. Also, if your $5 VPS provider doesn't give you a guarantee that the load balancer and all game instances are on hte same subnet, you may get significant additional latency from doing that.

#5298041 Hundreds of timers...

Posted by on 25 June 2016 - 05:12 PM

Just because a MMO emulator, generally written by students with a lot of time but not much experience, does something, doesn't mean that that's the right way :-)
A priority queue has O(log N) or better behavior for insert-new-element and find-next-element-to-run. Typically implemented as a heap.

Typically, the code to run your timer events looks like:

  timestamp_t now = current_timestamp();
  while (!queue.empty() && queue.leftmost_item().timestamp <= now) {
    timer t = queue.pop_leftmost();
It really is that simple. What will take time is the work actually done by each timer function.
If your timer drives everything (not necessarily a good idea) then you might want to make timer execute() queue something to a pool of worker threads, but that's really only a win if the locking overhead is much less than the CPU cost of running all the events, which means that most events cannot have many dependencies on other parts of the system.

#5298008 Server/Client architecture for turn-based card game developed with Unity3D

Posted by on 25 June 2016 - 11:29 AM

Any server technology can be the back-end for a turn-based card game. Web servers/services are very diverse and you should pick one that uses an environment you are familiar with.
(Nginx/PHP, Tomcat/Java, Nodejs/Javascript, Rails/Ruby, Flask/Pyton, Wai/Haskell, IIS/C#, ...)
Separately, any game server can probably also be used for a turn based game. Photon, Bolt, Lidgren, Smartfox, and a bunch of others. If you go that route, you should go with the server technology that has he best client libraries for your engine, and perhaps also pay attention to the server OS (do you prefer Windows or Linux for 24/7 uptime systems?)

Now, if you use Steamworks for match making, you might be better off also using Steamworks for the networking. That, in turn, means you should probably choose a server platform that has a ready-made Steamworks integration, and/or makes it easy to link in C++ code.
Steamworks is great if you want to tie into the existing Steam social community. The matchmaking is OK, but not necessarily a feature that's so special that you have to mutate the whole rest of your architecture just to support it.

You have to figure out whether you actually want a persistent process per "current game" that deals with everything from game rules to player chat, or whether you want the game state to be network-attached in some back end (anything from memcached through Redis to SQL) so that you don't need stateful sessions, and solve chat using some other method (or polling.)
This, too, determines your approach.

The solution that's probably the easiest to implement and easiest to scale, but isn't necessarily the cheapest per hosted game at small scale, would be to store each game instance in Redis, use a simple polling-based protocol over HTTP that polls maybe 1 or 2 times a second, and make "what each person has said" a part of the game state, returned through polling.
The two main operations would then be "get me game state later than X" and "this is my player action at time Y." The front-end web service servers would receive the request, read the game state from Redis, update according to requests/rules, write back to Redis, and then return to the players.
This is a 100% stateless application server, which scales really, really, well. Also, as all game state lives in a single key (could be Redis, or Cassandra, or Riak, or perhaps even MySQL) this will scale (shard) horizontally in a trivial way.
A back-end with time-to-live support (such as Redis EXPIRE keys) lets you forget about a game if neither player has made any move for some number of minutes/hours.

#5298007 20Hz Server Performance Dilemma

Posted by on 25 June 2016 - 11:16 AM

A game typically is a stream of continuous updates. Even if a player is just holding down a key, or just not holding down a key, you should keep sending that information to the server at your network tick rate.
If you use UDP, this will "correct" the server if some packet is lost. (Also, it's highly likely that the next packet will have the same state as the previous packet, so a loss may not cause any de-sync.)
If you use TCP, this is still useful, because it lets you figure out when the connection goes bad in real time (through timing.) Although I really don't recommend TCP for action games where movement matters.

Separately, the pattern that works best for almost all games with real-time movement is the [url=http://www.mindcontrol.org/~hplus/graphics/game_loop.html]canonical game loop[/quote] based on a fixed simulation rate, a possibly variable rendering rate, and a possibly fixed networking rate.
The 20 Hz you've selected sounds like a fine network rate, but may be too long a time step for good physical simulation.
It's totally OK to send more than one command packet in the same network packet. If you run physics at 60 Hz, you will have three input packets per network packet, and they will be put into the server simulation at three successive time steps after being received.

There's also the question about whether you want to run simulation on the server, or just "verify movement." If you don't run simulation, then a player will be able to "tunnel" through thin surfaces, such as walls and doors, because that's not a lot of movement in a single tick.

#5297887 Hundreds of timers...

Posted by on 24 June 2016 - 11:02 AM

Yes, a priority queue is absolutely the right way to do this.

Separately, never store something like "number of ticks until you're done," because that requires writing every tick to update. Writes to memory cost more than just reads, by a pretty large factor.
Instead, store either "time at which I'm done," or perhaps "time when I started, and how many ticks from start it will go away" (depending on what's easier for your display UI)
Given the "current tick" you can then calculate the current state. Compared to memory writes, additions and subtractions are free, and divisions are very cheap.

#5297706 Is there efficient FREE way yo encode / encrypt the resource files ? ( like u...

Posted by on 23 June 2016 - 09:57 AM

We have had such problem a while ago and decided for AES128

What is your thread model? If your threat model is intercept-in-flight then that makes sense.
If you're trying to protect against actions taken by the user who has your program on their own machine, the strength of your crypto scheme or key management doesn't really matter.

then you multiply the amount of data you need to distribute by the number of customers

Every customer already downloads the full executable/installer, so I don't see how that changes? You need to be able to encode the data in real time on your download servers, which is a little bit of code to write, but that's not so bad. The main draw-back would likely be that you can't use a CDN when you get to scale.

Watermarking 3 journalists who are to review your game is very different from watermarking 3,000 paying customers

If your download servers can apply the watermark procedurally, then it doesn't matter how many different values you want to watermark with.

#5297704 What About your compressed Audio Format?

Posted by on 23 June 2016 - 09:52 AM

First, TCP is not great for interactive audio. If you want to speak with people, you really want to use UDP.

Second, an alternative to GSM 6.10 might be the Opus codec. If you haven't evaluated that yet, you probably should.

#5297655 How To Handle User Interface That Needs To Read/Write Server-side Data

Posted by on 22 June 2016 - 08:47 PM

There's a difference between "authority" and "knowledge."
The client can know the entire inventory of the player.
The client can display the entire inventory, and let the player add/remove items; it can even show the user which things happen in response (can't hold both a shield and two-handed sword at the same time.)
When the player says "commit," the client sends a message to the server, saying "this is what I want to change about my equipment."
This is not quthoritative -- it's a request.
The server then verifies whether that request is valid (the objects requested are in fact owned, the player class is right, there's no mis-match between the objects, etc.)
Then the server applies the requeted changes, and sends new information to the clients that need to know.
So, it's totally okay to perform and show the result of rules on the client. If the client agrees with the server (no bugs, no hacking) then the end result from the server will be the same. If the client is hacked, or i there is a bug, what's shown on the client will not match the server outcome, and the server's state update will tell the client what it should show, instead.

#5297644 Is there efficient FREE way yo encode / encrypt the resource files ? ( like u...

Posted by on 22 June 2016 - 05:01 PM

Again, if you want to make the files moderately hard to read for a normal human being who's not a trained reverse engineer, XOR-ing the data by the output of a random number generator is a fine method.
That should be easy to do across platforms, too.

void encode(unsigned char *file, size_t size) {
    int seed = 2345;
    while (size-- > 0) {
        *file ^= (seed & 0xff);
        seed = (seed * 13 + 31 + *file) & 0xfff;

void decode(unsigned char *file, size_t size) {
    int seed = 2345;
    while (size-- > 0) {
        unsigned char tmp = *file;
        *file ^= (seed & 0xff);
        seed = (seed * 13 + 31 + tmp) & 0xfff;
This code, as written, should be portable across a very large number of systems and languages, as it assumes nothing more than "ints are at least 16 bits."
It also encrypts different data with different rotating keys, such that a simple XOR of two encrypted files won't trivially recover the key.

Is this "safe against all hackers?" No. But it's about as good as you can make it without involving things like kernel-level DRM modules and "trusted computing" hard-cryptography stuff.

#5297588 Is there efficient FREE way yo encode / encrypt the resource files ? ( like u...

Posted by on 22 June 2016 - 09:54 AM

First: If you don't actually HAVE to encrypt the data, the don't worry about it.
It's more important to make a fun game, and make sure that lots of people hear about your fun game!

Second: If you are licensing content where the licensing agreement requires that you do some kind of protection, then I second the recommendation for XOR with a pseudo-random stream. That's a perfectly legitimate encryption method, and the "security" of that system ends up being related to the seed (key) for the stream, and the random number generator.
But, as already pointed out: Your program needs to draw the bits to the screen. Someone who knows how to use a debugger, can copy the bits out of your program at that point. Thus, there exists no 100% fool-proof DRM/encryption system, and thus, building something that is "good enough" is the best you can do.

Third: If you are really ambitious, you could use a stronger random stream (like a SHA256 hash) and use a per-user seed -- encrypting the payload once per user. When a user starts up their game, have them connect to your server that tracks purchases by user ID (email address? phone number?) and serves the key to them. This lets you track if someone copies their game to too many other computers. If you also watermark the assets, it also lets you track who ended up leaking the data, once the data is leaked onto the internet anyway.
But, that's not necessary for any "indie" game. I know some of the really big development houses does something like that with closed alpha/beta versions, to know which testers they can trust, though. (They also watermark screen shots.)

#5297530 Peer-to-peer Massive Multiplayer Game

Posted by on 21 June 2016 - 10:29 PM

this architecture has the exact same advantages/disadvantages as a star-topology

Yes you did. And what we're trying to indicate is that, no, actually, it doesn't.

Anyway, you'll be done in another three days (7 days from June 17,) so we'll see how it works then. Looking forward to it!

#5297464 Peer-to-peer Massive Multiplayer Game

Posted by on 21 June 2016 - 10:31 AM

The architecture itself is really just a small modification of a star topology

Based on my experience with distributed systems and networking, that sounds a lot like "just a little bit pregnant" to me.