Before writing a byte to a socket, understand what carries it. The TCP/IP layers, how IP addresses and ports route data to the right program, and the journey a message takes across the network.
Networking is built in layers, each handling one concern and stacking on the one below. Your program sends data at the application layer; the transport layer (TCP or UDP) adds ports and, for TCP, reliability; the internet layer (IP) handles addressing and routing between machines; the link layer moves bits over the physical medium. You mostly work at the transport and application layers, but knowing the whole stack explains what a socket really does.
The TCP/IP model — each layer wraps the one above (adds a header):
APPLICATION your protocol (HTTP, a game protocol) — the actual message
|
TRANSPORT TCP or UDP — adds PORTS; TCP adds reliability/ordering
|
INTERNET IP — adds source/destination ADDRESSES; routes between hosts
|
LINK Ethernet/Wi-Fi — moves bits over the wire/air
Sending: your data gets a TCP header, then an IP header, then a frame,
then goes out. Receiving: each layer strips its header on the way up.
You program at TRANSPORT + APPLICATION; IP + link happen for you.Two numbers get data to the right place. An IP address identifies a machine on the network; a port number identifies a specific program on that machine. Together — an address plus a port — they form a socket endpoint, so "connect to 203.0.113.5 on port 7777" reaches exactly your game server process. Servers listen on well-known ports; clients get a temporary port assigned.
IP address -> WHICH machine e.g. 203.0.113.5 (or IPv6 2001:db8::1)
Port -> WHICH program on it e.g. 7777 (your game server)
endpoint = (ip, port) -> uniquely identifies one program to talk to
a connection is identified by FOUR things (the "4-tuple"):
(source ip, source port, dest ip, dest port)
-> that's how one server on port 7777 keeps thousands of clients separate.
Ports 0-1023 are "well-known" (need privilege); games pick a high port
(e.g. 7777, 27015). Clients are assigned a random "ephemeral" port.The network moves raw bytes, not language objects — so anything you send must be encoded to bytes and decoded on the other end. This is why serialization matters (a later course covers it for games). It also introduces byte order: multi-byte numbers must agree on endianness, and network protocols use big-endian ("network byte order"), so you convert when packing integers into packets.
import struct
# the network sends BYTES. encode before sending, decode on receipt.
msg = "hello".encode("utf-8") # str -> bytes
back = msg.decode("utf-8") # bytes -> str
# multi-byte numbers need an agreed BYTE ORDER. networks use big-endian:
packed = struct.pack("!I", 300) # '!' = network (big-endian), I = uint32
value = struct.unpack("!I", packed)[0] # 300
# '!' ensures both sides agree regardless of CPU endianness.
# (games pack many fields tightly into a packet — see the Game Networking course.)Three properties define a network link and dominate multiplayer design. Latency is the delay for a packet to arrive (round-trip time / ping); bandwidth is how much data per second the link carries; packet loss is the fraction of packets that never arrive. Games are latency-sensitive above all — you cannot make light travel faster, so netcode is largely about hiding latency and tolerating loss, the whole subject of the Game Networking course.
Three properties of any network path — internalize these:
LATENCY time for a packet to travel (one-way, or round-trip = "ping")
bounded by the speed of light: ~cross-country RTT ~= 30-80ms,
intercontinental 100-300ms. YOU CANNOT MAKE IT ZERO.
BANDWIDTH data per second the link sustains (Mbps). Usually plentiful;
games send SMALL packets FREQUENTLY, so latency > bandwidth here.
PACKET LOSS fraction of packets that vanish (congestion, bad Wi-Fi).
the internet does NOT guarantee delivery.
Games live and die by LATENCY + LOSS. Netcode = hiding latency and tolerating
loss (prediction, interpolation, lag comp — the Game Networking course).