The internet Brood War was built for: screeching modems, 56 kilobits per second, and hundreds of milliseconds of latency. Those limits didn't constrain the design — they were the design.
When StarCraft shipped, "online" meant one of three things, and none of them had bandwidth to spare.
Two players, one phone line each, connecting peer-to-peer. A 56k modem peaked near 56 kilobits/sec downstream and far less up — with round-trip latency often 150–300 ms. You could not afford to send game state.
At a LAN party, machines spoke IPX/SPX (Novell's protocol, the era's default for games) over the local network. Fast and low-latency, but the game logic couldn't assume it — the same code had to run over a modem too.
Blizzard's free service (launched 1997 with Diablo) handled matchmaking, chat, and ladder — finding you an opponent and brokering the connection. Critically, Battle.net mostly got out of the way once the match started: the actual in-game traffic was the lean command stream between the players, not a fat stream through Blizzard's servers. That's why it scaled cheaply.
A late-game StarCraft battle has on the order of hundreds of units, each with a position, facing, health, and order. Suppose you tried to stream that state. Even a stingy encoding — say 16 bytes per unit — for 400 units, 24 times a second, is:
400 units × 16 bytes × 24 fps × 8 bits = 1,228,800 bits/sec ≈ 1.2 Mbit/s
That's ~22× more than a 56k modem could carry — in the best case, ignoring overhead and the upstream being far slower. Streaming state was simply impossible. But the commands a player issues? A handful of clicks per second, a few bytes each. That fits in a whisper of bandwidth — and it's the same few bytes whether you command 4 units or 400.
drag the army size — see why lockstep was the only option on a 56k link
The command line barely moves because it doesn't depend on army size — it depends on how fast a human can click. That decoupling is the whole point.
"Peer-to-peer" means one specific thing: Blizzard's servers aren't in the gameplay loop. Battle.net matches you, then hands off. One player — the host — coordinates. No central server simulates the game, because there's nothing to simulate: every machine computes the full, identical game itself.
With up to 8 players, the job is smaller than it sounds:
Every property people associate with Brood War's feel falls out of the network budget:
| The constraint | The design it forced |
|---|---|
| Can't send state | Lockstep — send commands, simulate locally |
| Local simulation must match | Determinism — fixed-point math, seeded RNG |
| Round-trips are slow | Latency buffering — commands take effect 2 frames later |
| No authority to correct drift | Desync detection — rolling state checksums |
| Commands are tiny & ordered | Cheap replays — record the command stream, replay it |
1 + (n × 2) bytes, never more than 25 (actions.h:1005).OpenBW keeps the lockstep protocol but carries it over a modern async transport (Boost.ASIO) with interchangeable backends — so the identical command stream can run over a real socket, a Unix pipe, or in-process for tooling and AI:
| Backend | File | Use |
|---|---|---|
| TCP socket | sync_server_asio_tcp.h | networked play; DNS resolution, reuse-address |
| Unix domain socket | sync_server_asio_local.h | same-machine clients, low overhead |
| POSIX stream / generic socket | sync_server_asio_socket.h | shared framing & send-queue logic |
The wire framing is deliberately minimal — a 2-byte little-endian length prefix, then the payload:
// every message on the wire
[uint16_t size] // payload length, little-endian (header not counted)
[ payload ] // the command bytes
Reads happen in 0x1000-byte chunks; sends are queued per client and may span 0x2000-byte buffers (sync_server_asio_socket.h). Small, predictable, and easy to reason about — the same virtues the original needed on a modem.
The payload is the serialized player action — a 1-byte action ID followed by its parameters (see the action stream). Those bytes are produced once, locally, and broadcast verbatim to every peer. Each peer feeds the identical bytes into its identical simulation. Nothing in the message describes results — only the player's intent.
Because there's nothing for one to authoritatively simulate — every client already computes the full, identical game. A central state server would be pure overhead and added latency. Battle.net's job was matchmaking and brokering the connection; the host player coordinates the match itself, with no Blizzard server in the gameplay loop. That's also why a free service was viable in 1998: there's no per-match server cost. The downside is no authority to arbitrate cheating or repair a desync — hence the strict checksum approach instead of correction.