Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

hplus0603

Member Since 03 Jun 2003
Offline Last Active Yesterday, 03:06 PM
*****

#5050803 C++ and MySQL for the server

Posted by hplus0603 on 07 April 2013 - 01:51 AM

The FAQ for this forum has links to game network coding.

In very brief, to create a server, you can start as such:

1) Call socket() to create a TCP socket.
2) Call bind() to bind the socket to your given port, and IP address 0.0.0.0 (IPADDR_ANY).
3) Call listen() for basically historical reasons.
4) Now, enter a loop that does the following:
4.1) Put all active sockets in an FD_SET.
4.2) Call select() with that FD_SET to test readability of sockets. Perhaps use a timeout so you can run periodic events even if the server is idle.
4.3) For the listening socket, if it returns readable, it means someone is connecting; call accept() on it and allocate a data structure with incoming buffer and client information. (This is empty for now.) Put the mapping from socket ID to buffer/client information into a hash table.
4.4) For each connected socket that is readable by select(), call recv() once to attempt to fill up the incoming data buffer in the per-socket data structure. Recv() will not block the first time you call it after select() says it is readable.
4.4.1) Decode, remove, and dispatch any complete packet(s) that are in the receive buffer for this socket/client.
4.4.2) If recv() returns 0, or the client sends a "quit/disconnect" command, or the client is sending bad packets, close the socket, and de-allocate the buffer/client information structure for this socket.
4.5) Goto 4.1

That's really all there is to the basic server loop, based on select(). This will easily get you to many hundred simultaneous users.


#5049636 C++ and MySQL for the server

Posted by hplus0603 on 03 April 2013 - 11:50 AM

No, it is going to be neither fast nor secure to let a database be exposed to the greater Internet. One role of application servers is to filter the kinds of requests that a client will make, and turn them into sanitized back-end queries. There is not sufficient capabilities in SQL servers to do this; that's not what they're for.

Separately, for a real-time game, most developers end up reading the important data into RAM in a persistent process in the application server (call it "game server") and only write back to the database on occasional snapshots or specific events. This is usually done for efficiency purposes.


#5049255 Game Server security

Posted by hplus0603 on 02 April 2013 - 12:13 PM

You can of course also extend this to numeric values that change over time within the payload of the packet. But in general, I'd say that the client shouldn't be authoritative for any continuous values...

I would argue that clients are authoritative over the mouse position/movement, and mouse movement translates into camera/aim orientation (assuming FPS-style controls) and thus the client is authoritative for aim. While this makes aimbots easier to write, it's a necessary trade-off (and even without it, aimbots are entirely possible.)


#5049060 Game Server security

Posted by hplus0603 on 01 April 2013 - 08:36 PM

Should I catch this case and just close the connection?

Yes. As soon as something is not right, close the connection. Also, log this to some counter, perhaps correlated with client version reported on connection, so that you can tell if you have a bug that causes users to get disconnected because the client sends bad data :-)

Also, put a stringent max size on EVERYTHING. A maximum size on the message type. A maximum size on files downloaded or uploaded. A maximum size on strings. A maximum item count in arrays. And make those limits be fairly limited. This will avoid someone doing things like sending a "valid" packet that claims to have 2,000,000,000 items in it, and thus tying up your sever just receiving and dealing with that packet.

Another popular attack is sending malformed inner data. Say you have a "login" packet that looks something like: name:string, password:string, clientversion:varint.
Now, if strings are zero terminated, then someone can send a valid outer packet (type: login, length: whatever) but then not include a zero byte in the payload. Your decoding function may at that point run past the end of the packet, and read random memory. Don't do that! (Better is to length-prefix strings, and automatically cut them off at 255 bytes max.)

Even if you fix the string, someone might send a badly encoded varint. For example, let's say that varints are encoded with the high bit set when there's a continuation byte, and the high bit clear for the last byte; each lower 7 bits are data, little-endian. For example, the value 0xAA55 would be sent as:
(0xAA55 & 0x7f) | 0x80, ((0xAA55 >> 7) & 0x7f) | 0x80, ((0xAA55 >> 14) & 0x7f)
Now, someone could send a packet that contains the value 0x80 over and over again, causing your decoding logic to never break out of the varint decoding loop. Always establish a maximum length for a varint, or any data type, on the wire.

Once you have the serialization/de-serialization dealt with, the semantics of the packets matter. Don't treat something as "known good." For example, if an entity ID is in the packet, look up that entity ID in a hash table each time you see it. If it's not there, disconnect the player. If a property ID is in the packet, make sure it's valid, and if it's not, disconnect the player. If a floating point value is in the packet, make sure it's not NaN or Inf or denormal -- if it is, disconnect the player.


#5047709 [career] Mobile game server side question.

Posted by hplus0603 on 28 March 2013 - 11:54 AM

Mobile networking is like regular networking, except someone keeps pulling out the cable from your computer for 1 minute every 5 minutes.
If you can make a game that works under those conditions, you'll be well prepared.
Are you going to be the only one working on mobile services back-end, or will you join a team that's already doing it? If you're joining a team, you're likely to be able to learn from the others on the team. Don't be afraid of asking questions until you understand, because that's much better for the team than working on something you don't understand!


#5047091 Client - non dedicated server architecture

Posted by hplus0603 on 26 March 2013 - 07:29 PM

Yes, it's totally feasible to let players host servers.
The main problem you'll need to solve is "how do players who want to join, find a server to join?"
One option is a central matchmaker server, but you could just tell people to do port forwarding, and post their server IP/port on an internet forum, and that might work just fine for your game.


#5047090 .Net server and chat channels

Posted by hplus0603 on 26 March 2013 - 07:28 PM

I would make the channel be a binary ID in front of the text, rather than a substring within the payload.
Thus, the data could be:

[0x1, 0x5, "Hello"]
This would say "message type 1 (text chat) on channel 5, data "Hello".

The code for receiving command type 1 would then dispatch to the right channel:
Dictionary<byte, Channel> channels = new Dictionary<int, Channel>();

void DispatchChat(byte[] data) {
  Channel chan;
  if (!channels.TryGetValue(data[1], out chan)) {
    // no such channel
    return;
  }
  chan.ChatMessage(data);
}
There are many other ways of slicing this (such as dispatching on channel first, command second, or using a different container, or targeting messages at "objects" where one kind of "object" is a "channel" or ...)

Also: One thread per user works for small numbers of users (a few hundred, say.) For good performance and resource utilization, though, you want to use BeginReceive()/BeginSend() or ReceiveAsync()/SendAsync() and let the OS do the thread pooling for you.


#5044650 Unity Caching in Web Player, without WWW

Posted by hplus0603 on 19 March 2013 - 01:27 PM

I believe this is one of the ways that Unity starts making money from "real" uses of their web player. Last I checked into this (which was two years ago) there was no good way of loading game-like assets from non-Unity data; you had to convert to asset bundles on the server side, and you had to go through their caching layer, where you have to pay for more than 50 MB of local caching.
There is a WWW interface that allows you to issue a "GET" or "POST" but it's not quite to the level that you can trust a "streaming game experience" to it.

Again, this was about two years ago, so things may have changed since then. We ended up developing our platform on HTML5 + WebGL instead.


#5044317 Client hosted game that seems lik an MMO

Posted by hplus0603 on 18 March 2013 - 01:01 PM

For the cheating isse - who says a player who is the host has to be running the simulation for the zone they are in ?

A determined cheater will just run more than one machine, and find one of them hosting some instance that one of his players is in, and then proceed to cheat from there.


#5042467 Multiple Sockets Per Client

Posted by hplus0603 on 12 March 2013 - 03:56 PM

The port numbers are there to identify services. There are more than 255 kinds of services in the world, so 255 port numbers is not enough. (Some argue that 65535 is not enough, and strings should have been used, but it's too late to fix that now :-)

A connection is identified by a four-tuple of (remote IP, remote port, local IP, local port) which means that you can have up to 65535 connections in parallel from one machine to a specific service on another machine. That seems like it should be enough, although remember that TCP connections stay in TIME_WAIT state after being closed for a few minutes, and there actually exists cases where you'll run out! This is mostly for short-lived HTTP requests for service-oriented architecture type systems.

You *can* use a long-lived TCP connection for some messages, and a UDP connection you manage yourself for some other messages. It can work. But, if you're building the UDP part, you might as well put a simple reliability layer on top of that, as long as you don't use that for things like bulk download of large asset files, patches, etc. That will likely actually simplify the messaging/communications code.


#5040086 Smoothing Out Real-Time Movement

Posted by hplus0603 on 06 March 2013 - 01:10 PM

There was a long thread about this on the sweng-gamedev mailing list a few years back IIRC.
The main problem is that player/player interactions (a k a "collisions") suffers from latency.
The solutions suggested included:
- make the forward extrapolation of player data use a driving AI to get better projected trajectories than plain extrapolation
- have each player detect collisions locally, and if detected, let everyone know that "this player is crashing" -- that may not affect any other player (this is limited client-authoritative simulation)
- make collisions quite violent so that a "correction" camera snap isn't noticeable
- when in doubt, Just Add Smoke ™!


#5038910 How do I update text (or anything) in a game, in real time?

Posted by hplus0603 on 03 March 2013 - 08:28 PM

Hopefully I can pull this off with Game Maker somehow.

If the requirement is "has to be implemented within Game Maker" then that may be a pretty harsh requirement.

I agree with others: Spin up a web server that serves the "news and information" page. Web servers are great at distributing semi-static content. Load this from the game and display it. If you don't need the full HTML DOM / CSS / JavaScript engine, you could probably write a simple text-and-image renderer that understood just enough HTML to display your news blurb correctly.

Most web browsers pay attention to cache control headers, so you can mark your news data to expire a few hours from when it's fetched. That way, a client will re-load news only if it's been several hours since it last saw it.


#5038905 Idea for online multiplayer turn-based game with UDP

Posted by hplus0603 on 03 March 2013 - 08:21 PM

each server could stands a limit of CCU by using TCP

Single-core processes routinely deal with >100,000 connections over TCP these days. As long as you use efficient I/O -- libevent, boost::asio, or similar (or go direct to /dev/poll, I/O completion ports, or whatever your platform provides) you won't see a performance problem from TCP over UDP.

TCP consumes more resources when closing and re-connecting, that it does just staying connected but idle. Disconnecting and re-connecting a client while waiting for a move would be very inefficient.

Honestly, it sounds to me as if you're trying to optimize the wrong thing here. How many users do you expect to have playing at the same time? And how much are you able to pay to support that many users? The Amazon Free Usage Tier (a Micro ECC instance, free, for a year, and 20 GB of data transfer per month) can support >1,000 simultaneous online users of a turn-based game using TCP with no problems.

Also, you seem to be assuming things about TCP vs UDP that I'm not sure are true. UDP is not magically "cheaper" in any sense -- it just moves a lot of the management responsibility for connections onto your application, instead of using something ready-made in the kernel. It's still more or less the same work and same memory usage needed. The only gain of UDP is that, if there is packet loss, you don't have to wait for a re-transmit of older data before getting newer data delievered, so if sooner is more important than in-order (such as for VoIP, FPS games, etc,) then UDP may provide a better experience to the player.


#5038500 Java UDP Multicast problems with sending data

Posted by hplus0603 on 02 March 2013 - 01:36 PM

The server and client run on the same IP and same port, but I'm sure that is not the problem

When multiple processes use the same port number on the same host, then only one of them will get any particular incoming datagram. This may be great for scaling a single-threaded program across many cores (fork many processes and have them all bind to the same port) but it's certainly not good for your client/server game situation.

The client should not have to bind to any particular port number. Just let the UDP implementation assign a port number the first time you call sendto().


#5038496 RPG-like serverside spell/skill system

Posted by hplus0603 on 02 March 2013 - 01:30 PM

Plan your Systems first

While a plan certainly helps, there's a danger of going into analysis paralysis.

I think the most important part is to understand that re-factoring code is a natural part of the evolution of a system. Thus, you should make your overall code as easy to refactor as possible. This may mean using interfaces between each subsystem, so that each subsystem is less dependent on everything else. This may mean using consistent code formatting and naming conventions, so that search-replace and code movement is less prone to typos. And it very likely means writing good automated tests for each piece of functionality you develop, so you know that a re-factor doesn't break the functionality!




PARTNERS