_________ __                 __
        /   _____//  |_____________ _/  |______     ____  __ __  ______
        \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
        /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ \
       /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
               \/                  \/          \//_____/            \/
    ______________________                           ______________________
                          T H E   W A R   B E G I N S
                   Stratagus - A free fantasy real time strategy game engine

Module - Network

How does it work.

Stratagus uses an UDP peer to peer protocol (p2p). The default port is 6660.

UDP vs. TCP

UDP is a connectionless protocol. This means it does not perform retransmission of data and therefore provides very few error recovery services. UDP instead offers a direct way to send and receive datagrams (packets) over the network; it is used primarily for broadcasting messages.

TCP, on the other hand, provides a connection-based, reliable data stream. TCP guarantees delivery of data and also guarantees that packets will be delivered in the same order in which they were sent.

TCP is a simple and effective way of transmitting data. For making sure that a client and server can talk to each other it is very good. However, it carries with it a lot of overhead and extra network lag.

UDP needs less overhead and has a smaller lag. Which is very important for real time games. The disadvantages includes:

  • You won't have an individual socket for each client.
  • Given that clients don't need to open a unique socket in order to transmit data there is the very real possibility that a client who is not logged into the game will start sending all kinds of garbage to your server in some kind of attack. It becomes much more difficult to stop them at this point.
  • Likewise, you won't have a clear disconnect/leave game message unless you write one yourself.
  • Some data may not reach the other machine, so you may have to send important stuff many times.
  • Some data may arrive in the wrong order. Imagine that you get package 3 before package 1. Even a package can come duplicate.
  • UDP is connectionless and therefore has problems with firewalls.

I have chosen UDP. Additional support for the TCP protocol is welcome.

server/client vs. peer to peer

  • server to client

The player input is send to the server. The server collects the input of all players and than send the commands to all clients.

  • peer to peer (p2p)

The player input is direct send to all others clients in game.

p2p has the advantage of a smaller lag, but needs a higher bandwidth by the clients.

p2p has been chosen for in-game. s/c for the preparing room.

bandwidth

I wanted to support up to 8 players with 28.8kbit modems.

Most modems have a bandwidth of 28.8K bits/second (both directions) to 56K bits/second (33.6K uplink) It takes actually 10 bits to send 1 byte. This makes calculating how many bytes you are sending easy however, as you just need to divide 28800 bits/second by 10 and end up with 2880 bytes per second.

We want to send many packets, more updated per second and big packets, less protocol overhead.

If we do an update 6 times per second, leaving approximately 480 bytes per update in an ideal environment.

For the TCP/IP protocol we need following: IP Header 20 bytes UDP Header 8 bytes

With ~9 bytes per command and up to N(=9) commands there are 20+8+1+9*N(=120) bytes per packet. Sending it to 7 other players, gives 840 bytes per update. This means we could do 6 updates (each 166ms) per second (6*840=5040 bytes/s).

Network packet

  • [IP Header - 20 bytes]
  • [UDP Header - 8 bytes]
  • [Header Data:Type - 1 byte] if Type is one of the InitConfigMessage
  • [Header Data:SubType - 1 byte]
  • [Data - depend of subtype (may be 0 byte)] else
  • [Header Data:Types - N-1 bytes] (for N commands)
  • [Header Data:Cycle - 1 byte]
  • [Data:Commands - Sum of Xi bytes for the N Commands]

Putting it together

All computers in play must run absolute syncron. Only user commands are send over the network to the other computers. To reduce network traffic, commands are sent/executed every gameCyclesPerUpdate gameCycles. The command needs some time to reach the other clients (lag), so the command is not executed immediately on the local computer, but a delay (NetworkLag NetUpdates) later. Commands are stored in a circular array indexed by update time. Once each other players commands are received for a specified gameNetCycle, all commands of this gameNetCycle Each gameNetCycle, a package must be send. if there is no user command, a "dummy" sync package is send (which checks that all players are still in sync). If there are missing packages, the game is paused and old commands are resend to all clients.

What features are missing

  • The recover from lost packets can be improved, as the player knows which packets is missing.
  • The UDP protocol isn't good for firewalls, we need also support for the TCP protocol.
  • Add a server/client protocol, which allows more players per game.
  • Lag (latency) and bandwidth should be automatic detected during game setup and later during game automatic adapted.
  • Also it would be nice, if we support viewing clients. This means other people can view the game in progress.
  • The current protocol only uses single cast, for local LAN we should also support broadcast and multicast.
  • Proxy and relays should be supported, to improve the playable over the internet.
  • We can sort the command by importants, currently all commands are send in order, only chat messages are send if there are free slots.
  • password protection the login process (optional), to prevent that the wrong player join an open network game.
  • add meta server support, I have planned to use bnetd and its protocol.

API How should it be used.

InitNetwork1() Open port. Must be called by Lua

ExitNetwork1() Close port. Called internally and by Lua

::NetworkOnGameStart() Initialize msg stuff for ingame communication.

NetworkEvent() Manage network event (preparation room + ingame).

NetworkRecover() Do stuff to have again NetworkInSync == true

NetworkCommands() Network Updates : exec current command, and send commands to other players

NetworkFildes UDP Socket for communication.

NetworkInSync false when commands of the next gameNetCycle of the other player are not ready.

NetworkSendCommand() Send a normal unit order.

NetworkSendExtendedCommand() Send special command (diplomacy, ...)

NetworkSendChatMessage() Send a chat message to others player

NetworkQuitGame() Warn other users that we leave.

(C) Copyright 1998-2012 by The Stratagus Project under the GNU General Public License.
All trademarks and copyrights on this page are owned by their respective owners.