4
\$\begingroup\$

This is more or less like what I'm thinking up to now:

while(true)
{
    if (hasMessage)
    {
        handleTheMessage();   
    }
}

But while I'm receiving the player's input, I also have objects that need to be updated or, of course, monsters walking (which need to have their locations updated on the game client everytime), among other things.

What should I do? Make a thread to handle things that can't be stopped no matter what? Code an "else" in the infinity loop where I update the other things when I don't have player's input to handle? Or even: should I only update the things that at least one player can see? These are just suggestions... I'm really confused about it. If there's a book that covers these things, I'd like to know.

It's not that important, but I'm using the Lidgren lib, C# and XNA to code both server and client.

\$\endgroup\$
6
  • 1
    \$\begingroup\$ It's a basic question about programming a network game. You should read some tutorials. \$\endgroup\$
    – nathan
    Commented Nov 6, 2012 at 18:49
  • \$\begingroup\$ I don't think it's so basic, and yes, I read a lot before starting to ask. The problem that I can see here is that: if a message handling take too much time to be handled, monsters could be stopped for some time (for example). \$\endgroup\$
    – Renann
    Commented Nov 6, 2012 at 19:03
  • 1
    \$\begingroup\$ The answer is something along the line of message queues/buffers, handling a fixed set of messages per time step. Having everybody run at the same speed and wait for each other (lock-step). Client-Side prediction, transactions, ... and designing your server architecture in such a way that you know how much you can handle and to never have to handle so much each frame. However this is one of the most advanced topics in game programming and one of the hardest to get right. I suggest you start with some simpler networking scenario's. (Small number client-server architecture, etc..) \$\endgroup\$
    – Roy T.
    Commented Nov 6, 2012 at 19:07
  • \$\begingroup\$ So you think that the way to go (in this specific example of the monsters) should be done only for the players that are in the monster's view area? \$\endgroup\$
    – Renann
    Commented Nov 6, 2012 at 19:15
  • \$\begingroup\$ @RoyT. Actually I'm working now on a very simpler scenario... but that questions just came into my mind (as it will be one of the things that I'll have to implements sooner or later...) \$\endgroup\$
    – Renann
    Commented Nov 6, 2012 at 19:27

3 Answers 3

4
\$\begingroup\$

This is quite a basic question, although it might not seem like one. Networked games are no different to any other program in this regard - if you need the program to be responsive, you really have 4 options, listed in the order you should attempt them:

  1. make sure each operation is processed quickly (by disallowing any slow operations)
  2. set up slow operations so that they can be time-sliced and process a small part of it at a time until it's done
  3. split slow operations into multiple quick ones and process each part separately
  4. process slow operations in a separate process or thread, using (sometimes complex) synchronisation methods to communicate

90% of the time you can just go with the first option (changing a value, requesting some data). Most of the remainder are in the second category (eg. following a path).

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the answer! I want to leave this discussion opened for a little more. \$\endgroup\$
    – Renann
    Commented Nov 7, 2012 at 4:01
1
\$\begingroup\$

my network server engine has this architecture and has 3 main threads: SocketServerThread, ScheduledThread, GameServerThread. Game data is stored into DB, so there are other threads for DB connections (using a connectionPool)

-SocketServerThread manages all I/O data and new connections. When this thread receives data, it build a "input" message like (lenght:short, code:int, data:bytes) and send it to a shared structure: inputPriorityQueue. SocketServerThread produces "input" message and the only one that consume "outputMessage"

ScheduledThread manages specific scheduled events (game logic events and general server events) These events aren't generated by players inputs/actions, but usually by interal Cron jobs or scheduler. Example of these events are Monster AI, or player logout per x seconds inactivity. This thread can generate "input" message too, and put them in the "inputPriorityQueue" (processed by GameServerThread) or output messages, processed by SocketServerThread.

Then Another thread, GameServerThread, read "messages" from inputPriorityQueue, process them, update game server status and produces messages in the outputPriorityQueue.

SocketServerThread every 35ms reads all message it could read from "outputPriorityQueue" in a fixed maximum interval (for example 20ms), then for the other 15ms it is free to manage socket new connections and socket new incoming data. SocketServerThread Appends all socket avaible data into the Client buffer data, and checks this client buffer data for composing all "input" message it cans.

SocketServerThread is the only one who can consume outputPriorityQueue message.

The queues(input and output) are Priorityqueue, so i can manage message processing order.. for example, a server message like: "Server will be restarted in 30 seconds" could have a higher priority and processed immediatly.

\$\endgroup\$
0
\$\begingroup\$

The MMORPG server I am currently developing solves this problem with multi-threading. This is a simplified overview of the architecture:

One thread is listening to the client connections, interprets the data streams, and breaks them up into "event objects" which are then pushed onto an event queue.

Another thread handles the game loop. The loop starts with clearing the event queue. It then acts on the events and performs all other game logic.

When the game loop does something one or more clients need to be informed about, it will also create events. These events are collected in separate event queues for each client. A third thread serializes these events and sends them to the clients.

This architecture has the advantage that both input and output are completely separated from the game logic.

The biggest problem in such a multi-threaded architecture is to avoid concurrent access to the event queues. When one thread reads a queue while another one writes to it, you can run into all kinds of obscure bugs. So it's important to learn about the thread synchronization tools your programming language / platform / threading framework provides and use them correctly.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks for the answer! I want to leave this discussion opened for a little more. \$\endgroup\$
    – Renann
    Commented Nov 7, 2012 at 4:03
  • 1
    \$\begingroup\$ While having separate I/O threads can sometimes be helpful, it's worth noting that a lot of the low level I/O is automatically handled in a separate process by the OS anyway, being pulled off the network and buffered accordingly. So this approach doesn't always gain you much. \$\endgroup\$
    – Kylotan
    Commented Nov 7, 2012 at 16:02
  • \$\begingroup\$ The moment you accept an answer, the discussion is usually considered closed on the stackexchange network. \$\endgroup\$
    – Philipp
    Commented Nov 15, 2012 at 13:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .