Lesson 4: Game Server - Basics
Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.
Server Responsibilities
What belongs on the server?
Think of the server as four cooperating layers:
[ Network I/O ] receives bytes, sends bytes
↓
[ Sessions ] tracks connected players
↓
[ Simulation ] advances authoritative world state
↓
[ Rules ] validates actions and applies game logic
For this lesson, we keep the server in-memory and focused on basics. We are not saving accounts, maps, or characters yet — that belongs to Lesson 5: Game Server - Persistence.
A useful Java/Netty comparison: the network layer is like your channel pipeline, sessions resemble connection-scoped state, and the simulation/rules layer is your domain model. The difference is that game servers usually run on a strict tick cadence instead of purely request/response timing.

Sessions And Players
Connections are not characters
A common early mistake is to blur these together:
- Connection/session: a live network link to a client
- Account: a long-term identity, not covered yet
- Character/player entity: something inside the world simulation
For this lesson, we only need a minimal session table: when a connection joins, assign a session id; when it leaves, remove it.
This keeps the network boundary clean, just like we separated subsystems in Lesson 2.
```cpp
#include <iostream>
#include <string>
#include <unordered_map>
struct Session {
int sessionId;
std::string remoteAddress;
};
class SessionManager {
public:
int add(const std::string& remoteAddress) {
int id = nextId_++;
sessions_[id] = Session{id, remoteAddress};
std::cout << "connected session=" << id
<< " from " << remoteAddress << "\n";
return id;
}
void remove(int id) {
auto erased = sessions_.erase(id);
std::cout << "disconnect session=" << id
<< " removed=" << (erased ? "yes" : "no") << "\n";
}
void list() const {
std::cout << "active sessions: " << sessions_.size() << "\n";
for (const auto& [id, session] : sessions_) {
std::cout << " #" << id << " " << session.remoteAddress << "\n";
}
}
private:
int nextId_ = 1;
std::unordered_map<int, Session> sessions_;
};
int main() {
SessionManager sessions;
int alice = sessions.add("127.0.0.1:50100");
int bob = sessions.add("127.0.0.1:50101");
sessions.list();
sessions.remove(alice);
sessions.list();
(void)bob;
}
```
Thread Per Player?
True or false:
A good default MMORPG server design is to create one dedicated simulation thread per connected player.
Message Dispatch
Bytes become commands
In Lesson 3, the client learned packet framing: network bytes must be grouped into complete messages.
Once a full message reaches the server, the next step is dispatch:
raw packet → decoded message → handler → validated world mutation
For now, we can model messages with simple strings. Later, you might use binary packets, schemas, or generated serializers — but the routing idea stays the same.
```cpp
#include <iostream>
#include <sstream>
#include <string>
void handleLogin(int sessionId, const std::string& name) {
std::cout << "session " << sessionId << " login name=" << name << "\n";
}
void handleMove(int sessionId, int dx, int dy) {
std::cout << "session " << sessionId << " move intent dx=" << dx
<< " dy=" << dy << "\n";
}
void handlePacket(int sessionId, const std::string& packet) {
std::istringstream in(packet);
std::string type;
in >> type;
if (type == "LOGIN") {
std::string name;
in >> name;
handleLogin(sessionId, name);
} else if (type == "MOVE") {
int dx = 0;
int dy = 0;
in >> dx >> dy;
handleMove(sessionId, dx, dy);
} else if (type == "PING") {
std::cout << "session " << sessionId << " pong\n";
} else {
std::cout << "session " << sessionId << " unknown packet: " << packet << "\n";
}
}
int main() {
handlePacket(7, "LOGIN Ranger");
handlePacket(7, "MOVE 1 0");
handlePacket(7, "PING");
handlePacket(7, "CAST_FIREBALL");
}
```
Intent Vocabulary
In an authoritative server model, the client should send movement _____ rather than directly setting final world positions.
World Ownership
The world lives on the server
Even in this basic version, the server should own the world model:
- player entities
- monster entities
- map zones or regions
- temporary events like attacks, movement, and spawns
The client owns presentation: rendering, animation, input collection, prediction, and UI.
A helpful split:
Client: "I want to move north."
Server: "You moved 1 tile north; nearby players and monsters are now..."
This split is what will eventually let the same client support both normal play and god-mode editor workflows without letting arbitrary clients rewrite the live world.

Server Foundation
What we built conceptually
You now have the basic mental model for an MMORPG server:
- clients connect as sessions
- sessions send framed messages
- messages become validated commands
- the server tick mutates authoritative state
- clients receive the results, not permission to invent reality
This lesson intentionally stayed in memory and avoided durable storage. Next, in Lesson 5: Game Server - Persistence, we will add the ability to save and reload important server data without turning the simulation loop into a database tutorial.

