SSR: Network module description

In order to support multiplayer game SSR utilizes client/server architecture for the Internet or LAN games. The server is a separate application, which must be running on the computer accessible through the network to all players in the game. There are two main issues concerning client/server architecture: synchronization of the clients and server presence test. Server presence test is the fact, that a client should be aware of the server address. Currently TCP protocol is used for communication, which provides with a reliable communication between a server and its clients.

Synchronization

Using averaging technique solves synchronization of the clients with the server. Server has a master clock and all clients are synchronizing their clocks to a master clock. The client sends a special command (ping) to the server to retrieve the current server time. This is repeated for N times with 1-second interval. For each received value of the server time the client maintains the time the request was sent and received. For each received ping the lag is calculated in the following manner: I assume that times for a packet from server to client and backwards are the same, which gives me ability to estimate the trip time for the packet as a half time between times the ping was sent and received. This half time is added to a server time to determine the REAL timer value at the moment of the receiving the ping. When the very first ping is received, the timer is set to have REAL value. For all subsequent pings the lag value is calculated as a difference between REAL value for a ping and actual value when the ping was received. Once N pings were received they are sorted smallest lag first, then M<N biggest ping results are dropped and the rest is averaged, this average value is used to correct the current timer (slow it down or advance). This procedure is repeated each K seconds, to keep timers synchronized.

Server presence test

Using centralized registration point solves this issue. The simple web-based interface is provided using a CGI script written in Perl. There is a single point of failure because of the centralized registration. That is why I did not hardcode the location of the script inside of the program, but rather added it into a configuration file of the program. I also realize that it is not a proper way to design a program, if user would have to change the settings each time something happens with the server providing CGI service. In order to avoid manual modifications, I introduced another level of redirection, which means that the information about the registration script is stored in a simple text file on the web. If service provided by the hosting server fails, I would just need to change the redirection information in one file. If client of server fails to retrieve information from the registration script, they would look up a new location of the registration script.

Servers are registering themselves at startup time, supplying parameters about version, location and availability using http protocol. The proper way for the registration is:

<script>?version=VER&action=reg&name=SERVER_NAME&port=PORT&cont=CONT

Where:

VER - version of the server (is internal to the server)

SERVER_NAME - name of the server as given by the administrator

PORT - port on which the server is accepting new connections

CONT - geographical region, where server is running (supplemental information to provide users with some estimation for the speed of connection)

When server is shut down properly, it should unregister itself using the following link:

<script>?action=unreg

If registration commands were successful the page containing <poisitve_response_marker> will be returned.

The script will automatically detect the server IP and will provide information about version, IP address, port number and location to the clients. Clients should request this information from the following link:

<script>

The webpage with following information will be returned:

[anything here]
<start_marker>
VER;IP;PORT;NAME;CONT\n
:
<end_marker>
[anything here]

Protocols

When the server accepts the user connection, user is automatically joined to a special game, called "general chat", where all users can chat and negotiate the further actions. Figure 1 shows the protocol diagram for the user connected to the server.

Protocol diagram

Figure 1. Protocol diagram for a connected user.

While being connected to the "general chat" user also can send following commands:

  1. MSG_NAME to set its name
  2. MSG_GAME_INFO to request the information about custom games available for joining.
  3. MSG_NEWG to create a new custom game (the creator of the game is considered an administrator of the game)
  4. MSG_JOIN to join already created custom game
  5. MSG_DISCONNECT to gracefully disconnect from the server
  6. MSG_CHAT to send a chat message

While being connected to a custom game user is allowed to send the following commands:

  1. MSG_ENDG to end game (if received from administrator of the game) or disconnect form the game for all other players
  2. MSG_START to start the game (game will not be available for joining once it is started), this command can be send only by administrator of the game
  3. MSG_CHAT to send a chat message
  4. MSG_UPDATE to update information about actions taken by the player
  5. MSG_PING to synchronize the server timer to the client timer
  6. MSG_SYNC_CHECK to check clock synchronization
  7. MSG_GAME_PARAM_UPDATE to update parameters of the game (can be send only by admin, before the game was started)

Implementation

All commands have the common structure: first two bytes represent the length of the command, the third byte is the type of the command, and the rest of the bytes are the data bytes. Some commands could require 0 bytes of data and some could have the variable number of data bytes send. Using the length field, allows having commands with maximum of 65,533 data bytes. And there are 255 types of different commands. Currently less than 16 commands are used.

Special class CNetMan was designed to serve as wrapper for sockets. It has only static members and functions, which allows to use it without instantiation, though some initialization is required (in windows implementation only), the server and the client use this class to communicate with each other. CSSRServer class encapsulates all server functionality, while CNetClient class encapsulates client functionality.
Quick Links:

 News
 Description
 Screen Shots
 Downloads
 Custom Levels
 Source Code
 Help/FAQ
 Want to help?
 Credits
 Disclaimer


Tech docs:

 Documentation


Team:

sjcomp logo
sjcomp

Future
Developments


Useful links:

sjgui logo

opengl logo

openal logo

Audiere

boost logo

nehe logo

Caligari

Last modified:


rax.ru:shown(hits in 24h,visitors in 24h and today)