Skip to content
Lesson 9.3Network Messages, Authority, and IPC

Protocol Capture and Message Framing

Learn how a short local capture reveals message direction, boundaries, and the bytes associated with one game action.

Lesson 9.3
Read or listenPrint chapter or book
About 17 minutes

Keyboard shortcuts

?
Open this guide
Alt + B
Show or hide the lesson list
Alt + O
Show or fold the lesson outline
Alt + N
Open or close notes
Alt + H
Toggle semantic colours
Alt + D
Toggle page brightness
Alt + C
Toggle code brightness
← →
Move through a focused code trace
Home End
First or final step in a focused trace
Escape
Close this guide or an open panel

Reader shortcuts pause while you type in a text field.

Cheatsheet for Lesson 9.3Key ideas, reference and questions

A one-page summary of “Protocol Capture and Message Framing” you can keep beside your notes. Plain Markdown.

Lesson 9.3 — Protocol Capture and Message Framing: cheatsheet

  • Remember: A capture records traffic. Controlled actions and repeat comparisons connect those bytes to meaning.
  • Also useful: Picture TCP as one long ribbon: reads cut pieces from it, while your parser identifies complete messages.

Key terms

  • socket: A socket is an operating-system object representing one endpoint.
  • encapsulation: This wrapping is encapsulation.
  • OSI model: The OSI model names seven conceptual layers: application, presentation, session, transport, network, data link, and physical.
  • WebSocket: A WebSocket is a two-way framed-message protocol, useful for browser lobby chat.
  • wesnothd: For the Wesnoth 1.14.9 lab, keep 15000: that is wesnothd’s default listening port.
  • read_exact: read_exact is appropriate only after a validated frame length tells you exactly how many bytes belong to the next piece.

Formulas and patterns

  • tcp.port == 15000

Review

  • Q: Which capture method best reveals how one local game action is encoded? A: Record a quiet baseline, do one action, then compare changed bytes and timing
  • Q: How can a TCP stream carry one game message? A: It may be split across segments, or share one with other messages
Download cheatsheet (.md)

Lesson 9.1 showed that one game message can arrive across two TCP reads. A packet capture lets us inspect the bytes on the way, but its packet rows are not automatically game-message rows. We will send one distinctive lobby message, then follow its bytes in both directions.

An application message is not the same thing as an IP packet or TCP segment. Each layer has a different job:

game protocol message login, chat, lobby update
TCP byte stream ordered, reliable bytes between two sockets
IP packet routed data between host addresses
link/loopback capture what the capture interface records

TCP may split one game message across several segments or combine bytes from several messages in one segment. Retransmissions can repeat packet data. The receiving application sees an ordered stream, so protocol parsing needs its own framing rule such as a length prefix or delimiter.

This board needs JavaScript to move things around. Here is the lesson’s sorting:

Game protocol message
  • A login message. Login, chat and lobby updates are game protocol messages. That is the level your parser works at.
  • A length prefix saying where a message ends. The receiver sees an ordered stream, so protocol parsing needs its own framing rule such as a length prefix or a delimiter.
TCP byte stream
  • Bytes arrive in order, none missing. That is the TCP promise: an ordered, reliable stream of bytes between two sockets.
  • The four-tuple: source address and port, destination address and port. A TCP connection is identified by these four values, which is why one connection reads differently in each direction.
  • One game message split across several segments. TCP may split one message across several segments or combine bytes from several messages into one. A segment boundary is not a message boundary.
IP packet
  • Routing data between host addresses. Moving data between hosts by address is the IP packet’s job.
Capture
  • The row you see in the capture tool. A capture records bytes and timing at one point. A row there is not automatically a game message, and it cannot say why it was sent.

A socket is an operating-system object representing one endpoint. A TCP connection is identified by source address, source port, destination address, and destination port—the four-tuple used below.

Our capture stays local. To understand the wider journey, imagine a client joining match 42 and downloading its map from assets.example. Configuration, name lookup, delivery, and game permission solve different parts of that trip.

On a typical IPv4 LAN, DHCP gives a device an address lease and network configuration; options can supply a router and DNS servers. It configures the device, not the remote game’s identity. DHCP and its options specify that exchange. Static configuration and other address-assignment systems are also possible.

DNS resolves a name such as assets.example to records including IP addresses. A resolver can reuse an answer until its cache lifetime expires; name resolution does not deliver the map. The client then connects to the chosen endpoint. DNS concepts explain this separate lookup.

HTTP is the web’s request/response protocol. HTTPS carries that exchange over an authenticated, encrypted connection. A CDN can serve a cached map from an edge location. A cache miss may require an origin fetch; DNS answer caching and content caching have different lifetimes. Account requests still need their own authentication and cache policy. Cloudflare’s request journey shows these boundaries.

DHCP: a device joins the LANA device with no address asks the network for a lease. The reply also names the router and the DNS servers.
  1. Control DISCOVER (broadcast)

    Step 1: New device to DHCP server

    The device has no address yet, so it shouts to everyone on the LAN: is there a DHCP server?

  2. Control OFFER: 192.168.1.40

    Step 2: DHCP server to New device

    The server proposes an address and a lease time, plus the router and DNS server addresses.

  3. Control REQUEST: I accept 192.168.1.40

    Step 3: New device to DHCP server

    The device accepts one offer. If several servers answered, this tells the others to withdraw.

  4. Control ACK: lease confirmed

    Step 4: DHCP server to New device

    The lease is now recorded. The device configures itself; it has learned nothing about any game server yet.

A device with no address asks the network for a lease. The reply also names the router and the DNS servers.

DNS: from a name to an addressA resolver follows the name to the CDN and returns one address. Nothing is downloaded yet.
  1. Request assets.example?

    Step 1: Client to Resolver

    The client asks the resolver it was configured with (often learned through DHCP).

  2. Alone Check cache: nothing fresh

    Step 2: Resolver (alone)

    A cached answer that has not expired would end the lookup here.

  3. Request assets.example?

    Step 3: Resolver to Site's DNS

    The resolver asks the name servers responsible for the name. Root and top-level referrals are left out to keep the picture short.

  4. Reply CNAME assets.example.cdn.example

    Step 4: Site's DNS to Resolver

    The site points its name at the CDN’s name. The site’s DNS does not hold the file or the final address.

  5. Request assets.example.cdn.example?

    Step 5: Resolver to CDN's DNS

    The resolver now asks the CDN’s name servers about the CDN’s own name.

  6. Reply A 203.0.113.7 · TTL 30 s

    Step 6: CDN's DNS to Resolver

    The CDN chooses an edge near the resolver and sets a short lifetime, so it can steer players elsewhere soon.

  7. Reply 203.0.113.7

    Step 7: Resolver to Client

    The resolver remembers the answer for 30 seconds and returns it. The client has an address, not the map.

A resolver follows the name to the CDN and returns one address. Nothing is downloaded yet.

CDN edge with a fresh copyAfter the connection and TLS handshake, a nearby edge answers from its cache.
  1. Request HTTPS: GET /maps/42.bin

    Step 1: Client to CDN edge

    The client connects to 203.0.113.7, completes the TLS handshake, then asks for the map.

  2. Alone Cache lookup: fresh copy found

    Step 2: CDN edge (alone)

    The edge may reuse a stored copy while the origin’s cache rules say it is still fresh.

  3. Reply 200 OK + map bytes

    Step 3: CDN edge to Client

    The map arrives from a nearby machine; the origin never saw this request.

After the connection and TLS handshake, a nearby edge answers from its cache.

CDN edge without a copyA miss climbs the cache hierarchy toward the origin, and each cache may keep the answer on the way back.
  1. Request HTTPS: GET /maps/42.bin

    Step 1: Client to CDN edge

    The request is the same as before; the client cannot tell hit from miss.

  2. Alone Cache lookup: miss

    Step 2: CDN edge (alone)

    The edge has no usable copy.

  3. Request GET /maps/42.bin

    Step 3: CDN edge to Regional cache

    A larger regional cache is asked before the distant origin.

  4. Request GET /maps/42.bin (miss too)

    Step 4: Regional cache to Origin

    The regional cache also misses, so it fetches from the origin storage.

  5. Reply 200 OK + map bytes

    Step 5: Origin to Regional cache

    The origin supplies the file. The regional cache stores a copy if the response headers allow it.

  6. Reply 200 OK + map bytes

    Step 6: Regional cache to CDN edge

    The edge receives the file and can store it too.

  7. Reply 200 OK + map bytes

    Step 7: CDN edge to Client

    The player waits for the whole chain once. The next nearby request is a hit until the copy expires.

A miss climbs the cache hierarchy toward the origin, and each cache may keep the answer on the way back.

An IPv4 lease configures the client. DNS returns an address; only the later HTTPS connection retrieves the asset from the CDN, with an origin fetch on a cache miss.

A LAN, or local area network, joins nearby devices through links such as Ethernet or Wi-Fi. In this example, an Ethernet frame carries an IP packet, which carries a UDP datagram, which carries game bytes. This wrapping is encapsulation. A switch forwards link frames; a router forwards the IP packet onto another link with a new link frame. Physical signaling carries the bits on each link.

The OSI model names seven conceptual layers: application, presentation, session, transport, network, data link, and physical. The Internet’s TCP/IP model commonly groups application work, transport, Internet/IP, and link work. These models describe responsibilities, not seven mandatory headers. Our existing layer board remains useful: identify the job before assigning a name. Internet host requirements organize the protocol suite by these responsibilities.

The journey of one game messageHeaders are added on the way down, then removed on the way up. Play it step by step, or change the message size.
Ethernet header14 BIP header20 BUDP header8 BGame message24 BCheck sequence4 B

A 24-byte message becomes a 32-byte datagram, a 52-byte IP packet and a 70-byte frame: 46 of 70 bytes (66%) are wrapping.

Sending computer

  1. User space Game code calls send()

    The message sits in the program’s own memory. The program hands it to the socket API; it builds no headers itself.

  2. Kernel The kernel copies it into the socket’s send buffer

    The operating system copies the bytes out of the program’s memory into a buffer owned by the socket. send() can return once the copy is made; that says nothing about arrival.

  3. Kernel The transport layer adds its header

    UDP adds 8 bytes: ports, length, checksum. TCP adds 20: ports, sequence and acknowledgement numbers, flags, window, checksum. The result is a datagram (UDP) or a segment (TCP).

  4. Kernel The IP layer adds the IP header

    Twenty bytes with the source and destination addresses, a time-to-live and the protocol number. The kernel also consults its routing table to choose the next hop and the outgoing interface. The result is a packet.

  5. Kernel The packet waits in an output queue

    When several packets are ready, a queue decides which one the card gets next. Linux calls this the queueing discipline, or qdisc. Other systems have comparable queues under other names.

  6. Kernel The link layer wraps it in an Ethernet frame

    A 14-byte header holds the next hop’s MAC address, this card’s MAC address and the EtherType (0x0800 means IPv4). A 4-byte check sequence goes at the end, usually computed by the card. A frame shorter than 64 bytes is padded.

  7. Network card The driver hands the frame to the card, which sends bits

    The driver places a descriptor for the frame in a ring buffer in memory. The card reads the frame by direct memory access and turns each byte into signals on the cable or radio: bits.

Between the computers

  1. On the wire A switch forwards the frame

    A switch reads only the Ethernet header and sends the frame out of the port where the destination MAC address was last seen. The IP packet inside is untouched.

  2. On the wire A router moves the packet onto the next link

    The router throws away the old Ethernet header and check sequence, lowers the IP time-to-live by one, recalculates the IP header checksum and wraps the same packet in a new frame. The transport header and the data are not touched.

Receiving computer

  1. Network card The receiving card accepts the frame

    The card checks the destination MAC address and the check sequence; a damaged frame is dropped. A good frame is written into a ring buffer in memory by direct memory access, and the card raises an interrupt.

  2. Kernel An interrupt, then deferred processing

    The CPU pauses its work to run a short interrupt handler, which schedules the longer work for later. On Linux that is a softirq run by ksoftirqd; on Windows it is a deferred procedure call. That work empties the ring buffer.

  3. Kernel The Ethernet header is removed

    The EtherType says the payload is IPv4, so the packet goes to the IP layer. The link header and trailer have done their one-hop job.

  4. Kernel The IP header is checked and removed

    The kernel verifies the header checksum and that the destination address is this computer, then reads the protocol number (17 means UDP, 6 means TCP) to choose the transport layer.

  5. Kernel The transport layer finds the socket

    The destination port (for TCP, the whole four-tuple) identifies the socket. TCP also acknowledges, reorders and discards duplicates. The data is placed in the socket’s receive buffer.

  6. User space Game code calls recv()

    The kernel copies the bytes from the receive buffer into the program’s memory. Only now does the program see them. With TCP, one recv() need not return exactly what one send() sent, so the game must mark its own message boundaries.

Complete journey shown.

The same layers, named two ways. The OSI model is a teaching map; real stacks follow the TCP/IP grouping.
OSI layerTCP/IP modelUnit of data
7. ApplicationHTTP, FTP, your game protocolApplicationData
6. PresentationEncoding, compression, TLS encryption
5. SessionKeeping a conversation open
4. TransportTCP, UDPTransportSegment (TCP) or datagram (UDP)
3. NetworkIP; routersInternetPacket
2. Data linkEthernet, Wi-Fi; switchesLinkFrame
1. PhysicalCables, radio, the network cardBit

Maximum data in one Ethernet frame: 1,500 bytes of IP packet, so 1460 bytes of TCP data or 1,472 bytes of UDP data without fragmentation.

The same game bytes are wrapped inside a UDP datagram or TCP segment, an IP packet and an Ethernet frame. A router replaces the link wrapper for the next hop. The OSI/TCP-IP mapping is conceptual, not a literal count of wire headers.

Choose the delivery contract, then the application protocol

Section titled “Choose the delivery contract, then the application protocol”

If middle bytes are lost, TCP recovers them before exposing later bytes in its ordered stream. UDP can deliver a later datagram without the missing one; the game decides whether to replace stale state or add its own recovery. Neither transport acknowledgment proves the server accepted a purchase. TCP and UDP specify those different contracts.

One lost packet: TCP waits, UDP moves onFive messages leave one per tick and need one tick to arrive. Packet 3 is lost on its first try. Choose other packets, or move through time.

TCP Gives the game bytes in order, so one missing packet holds back everything after it.

TCP timeline. Columns are ticks of time; messages are numbered from 1.
Row01234567
Sent123453
Arrives12453
Held back445
Game receives12345

UDP Gives the game each datagram as it arrives, in whatever order, and never resends.

UDP timeline. Columns are ticks of time; messages are numbered from 1.
Row01234567
Sent12345
Arrives1245
Game receives1245
  • 1 sent
  • 1 lost on the way
  • 1 sent again by TCP
  • 1 reaches the computer
  • 1 held back
  • 1 handed to the game

TCP resends message 3 and gives the game all 5 in order, finishing at tick 7. Messages that had already arrived were held back: message 4 waits 3 ticks; message 5 waits 2 ticks. UDP gives the game messages 1, 2, 4 and 5 as each arrives and never delivers 3 on its own: the game decides whether to ask again or move on to newer data.

The timer is a simplification: real TCP can resend sooner when later packets arrive and the receiver keeps repeating the same acknowledgement. The ordering rule is real. TCP also needs a three-packet handshake before its first data; UDP can send at tick 0.

What each wrapper costs: a 8-byte UDP header or a 20-byte TCP header
UDP · 8 bytes
Source port16 bitsDestination port16 bits
Length16 bitsChecksum16 bits
TCP · 20 bytes without options
Source port16 bitsDestination port16 bits
Sequence number32 bits
Acknowledgement number32 bits
Offset4 bitsReserved + flags12 bitsWindow16 bits
Checksum16 bitsUrgent pointer16 bits
Options0 to 40 more bytes, only when needed
Source port
Identifies the sending socket on its computer.
Destination port
Identifies the receiving socket on its computer.
Length
Header plus data, in bytes.
Checksum
Detects corrupted bits in the header and data.
Sequence number
Position in the byte stream of the first data byte in this segment.
Acknowledgement number
The next byte the sender of this segment expects to receive.
Offset
Header length in 32-bit words; 5 means 20 bytes.
Reserved + flags
Flag bits such as SYN, ACK, FIN and RST say what kind of segment this is.
Window
How many more bytes the sender of this segment will accept (flow control).
Urgent pointer
Used only with the URG flag, which is rarely used.

TCP application messages still need framing: a lost packet changes timing, not message boundaries.

A socket is the local operating-system endpoint already introduced above. A WebSocket is a two-way framed-message protocol, useful for browser lobby chat. The RFC 6455 handshake uses HTTP/1.1 Upgrade; wss protects the exchange with TLS, Transport Layer Security, which authenticates the server and protects data in transit. HTTP/3 also has a WebSocket mapping, so an Upgrade handshake is not universal. Game authorization remains separate.

QUIC v1 runs over UDP but supplies its own reliable streams and loss recovery, using TLS 1.3 for connection security. HTTP/3 maps HTTP requests and responses onto QUIC. Loss affecting one stream need not block unrelated stream delivery, although streams share connection congestion limits. QUIC is not “unreliable HTTP,” and HTTP/3 is not a synonym for every game’s UDP protocol. The standards are QUIC v1, QUIC with TLS, and HTTP/3.

Two message paths, two socket typesBoth end at a socket, but the layers above it differ. Point at a layer to read what it does.

Secure WebSocket (RFC 6455)

HTTP/3 (RFC 9114)

Game message
The text or bytes your game sends, such as "join lobby 7". Your own rules decide what it means and who may send it.
WebSocket frame
A small header (opcode, length, a mask on frames the client sends) followed by the message. Frames keep message boundaries that raw TCP does not have.
TLS 1.3 record
Encrypts and authenticates the frames. The server’s certificate proves who it is.
TCP connection
Delivers the TLS bytes reliably and in order. One lost packet holds back everything after it on this connection.
TCP socket
The program’s endpoint for this connection, named by local and remote address and port. A socket is an operating-system object, not a message format.
IP packets and link frames
Routers move the packets; each link wraps them in its own frame.
Game request
An HTTP request such as a map download or an account call.
HTTP/3 frames
HEADERS and DATA frames carried on one request stream.
QUIC streams
Independent ordered byte streams inside one QUIC connection. Loss on one stream need not stall the others.
QUIC packets with TLS 1.3
QUIC does its own loss recovery, congestion control and encryption. TLS 1.3 is part of its handshake.
UDP socket
A datagram endpoint. Each QUIC packet travels inside one UDP datagram.
IP packets and link frames
The same delivery path as before.
  • Application meaning
  • Protection
  • Delivery
  • Routing and links

Inside one QUIC datagram (after the handshake)

UDP header Visible to the network
Source port, destination port, length and checksum. Routers, firewalls and address translators read these, so they cannot be hidden.
Flags byte Header-protected
Says this is a short-header packet and holds the key phase and packet-number length. Some of its bits are masked by header protection.
Destination connection ID Visible to the network
Lets the receiver find the connection even if the sender’s address changed, for example when a phone moves from Wi-Fi to mobile data.
Packet number Header-protected
Counts packets so the receiver can acknowledge them. Header protection hides it from observers.
STREAM frame Encrypted and authenticated
Stream ID, offset, length and a slice of that stream’s data. The offset lets the receiver put slices back in order even if packets arrive out of order.
Other frames Encrypted and authenticated
Acknowledgements, flow-control updates and more can share the same packet with STREAM frames.
Authentication tag Encrypted and authenticated
A checksum only the two endpoints can compute. If any protected byte changed on the way, the packet is rejected.

Handshake packets use a longer header with version and both connection IDs; this is the layout most packets have afterwards. Sizes follow QUIC version 1 (RFC 9000 and RFC 9001).

To compare how these protocols begin, step through one conversation for each.

HTTP/1.1 over TCPA connection first, then one request and one response.
  1. Control TCP handshake: SYN

    Step 1: Client to Server

    HTTP/1.1 normally runs on TCP, so the connection is set up first. The three handshake packets are drawn as one step here.

  2. Request GET /lobby HTTP/1.1

    Step 2: Client to Server

    The request names a method, a path and headers. HTTP itself is readable text.

  3. Reply 200 OK + body

    Step 3: Server to Client

    The response carries a status code, headers and the content. The connection can stay open for the next request.

A connection first, then one request and one response.

HTTPS: HTTP inside TLS 1.3The same request, after both sides have agreed on keys.
  1. Control TCP handshake first

    Step 1: Client to Server

    TLS rides on a TCP connection, so TCP is set up before any TLS message.

  2. Encrypted ClientHello + key share

    Step 2: Client to Server

    The client offers its supported algorithms and a public key share.

  3. Encrypted ServerHello + key share + certificate

    Step 3: Server to Client

    Both sides combine the key shares into the same session keys. The certificate proves the server’s identity, and it already travels encrypted.

  4. Encrypted Finished

    Step 4: Client to Server

    The client checks the certificate and confirms the handshake. Now encrypted application data can flow.

  5. Encrypted Encrypted: GET /lobby

    Step 5: Client to Server

    The HTTP request is the same text as before, but an observer on the path sees only encrypted bytes.

  6. Encrypted Encrypted: 200 OK + body

    Step 6: Server to Client

    The response is protected in the same way.

The same request, after both sides have agreed on keys.

HTTP/3 over QUIC and UDPQUIC joins the transport handshake and TLS 1.3, then carries independent streams.
  1. Encrypted Initial: ClientHello + key share

    Step 1: Client to Server

    QUIC runs over UDP datagrams and includes TLS 1.3 in its own handshake, so transport and security start together.

  2. Encrypted Initial/Handshake + certificate

    Step 2: Server to Client

    The server answers with its key share and certificate, protected as the handshake proceeds.

  3. Encrypted Finished + first request

    Step 3: Client to Server

    The client can send its HTTP/3 request on a new stream as soon as the keys are ready.

  4. Encrypted Stream 0: HTTP response

    Step 4: Server to Client

    Each request uses its own stream, identified by a stream ID.

  5. Encrypted Stream 4: another request

    Step 5: Client to Server

    Streams are independent. A lost packet carrying one stream need not stall the other stream, although both share the connection’s congestion limits.

QUIC joins the transport handshake and TLS 1.3, then carries independent streams.

WebSocket: upgrade, then both waysAn HTTP request turns the connection into a two-way message channel.
  1. Request GET /chat + Upgrade: websocket

    Step 1: Client to Server

    The handshake is an ordinary HTTP/1.1 request that asks to switch protocols. With wss it runs inside TLS.

  2. Reply 101 Switching Protocols

    Step 2: Server to Client

    The server agrees. From now on the same connection carries WebSocket frames, not HTTP messages.

  3. Data Frame: join lobby 7

    Step 3: Client to Server

    The client sends a framed message whenever it likes.

  4. Data Frame: lobby 7 roster

    Step 4: Server to Client

    The server can reply at any moment; no new request is needed.

  5. Data Frame: player joined

    Step 5: Server to Client

    The server can also push a message nobody asked for. That is why it suits live chat.

An HTTP request turns the connection into a two-way message channel.

TCP: connect, send, closeReliable ordered bytes need a handshake, acknowledgements and a teardown.
  1. Control SYN

    Step 1: Client to Server

    The client proposes a connection and its starting sequence number.

  2. Control SYN + ACK

    Step 2: Server to Client

    The server agrees, proposes its own starting number and acknowledges the client’s.

  3. Control ACK

    Step 3: Client to Server

    The client acknowledges the server’s number. Both sides now agree on the connection.

  4. Data Data: 100 bytes (seq 1–100)

    Step 4: Client to Server

    Every byte has a sequence number so the receiver can put bytes in order and spot gaps.

  5. Control ACK 101

    Step 5: Server to Client

    The acknowledgement names the next byte the server expects, which confirms bytes 1 to 100.

  6. Control FIN

    Step 6: Client to Server

    The client has nothing more to send and starts closing its direction.

  7. Control ACK + FIN

    Step 7: Server to Client

    The server acknowledges and closes its own direction too.

  8. Control ACK

    Step 8: Client to Server

    The final acknowledgement finishes the close. The client keeps the connection record briefly to catch stray late packets.

Reliable ordered bytes need a handshake, acknowledgements and a teardown.

UDP: just send a datagramNo setup, no acknowledgements, no automatic resend.
  1. Data Datagram: position update #41

    Step 1: Client to Server

    There is no handshake. The first packet already carries game data.

  2. Data Datagram: world snapshot

    Step 2: Server to Client

    Any reply is another independent datagram, sent when the server decides to send it.

  3. Data Datagram: position update #42

    Step 3: Client to Server

    If a datagram vanishes nothing is resent for you. The game’s own sequence numbers can show the gap.

No setup, no acknowledgements, no automatic resend.

SMTP: mail moves between serversA short text conversation hands the message from one mail server to the next.
  1. Request EHLO, MAIL FROM, RCPT TO

    Step 1: Sender’s app to Sender’s server

    SMTP is a text conversation. The client names itself, the sender and the recipient before any message is sent.

  2. Data DATA: headers + body

    Step 2: Sender’s app to Sender’s server

    Then the message itself, ending with a line that holds only a dot.

  3. Reply 250 OK, queued

    Step 3: Sender’s server to Sender’s app

    The server accepts responsibility for delivering the message.

  4. Request Relay: the same SMTP commands

    Step 4: Sender’s server to Recipient’s server

    The server finds the recipient domain’s mail server through DNS and repeats the conversation with it.

  5. Reply 250 OK, accepted

    Step 5: Recipient’s server to Sender’s server

    The receiving server takes the message.

  6. Alone Store in the recipient’s mailbox

    Step 6: Recipient’s server (alone)

    Reading mail later uses other protocols such as IMAP. SMTP only moves the message along.

A short text conversation hands the message from one mail server to the next.

FTP: commands and files on separate connectionsOne connection carries commands; a second connection carries each file.
  1. Control Control: USER, PASS

    Step 1: Client to Server

    Commands travel on the control connection (port 21). Plain FTP sends the password unencrypted; SFTP and FTPS are the protected options.

  2. Control Control: 230 logged in

    Step 2: Server to Client

    Numeric reply codes say what happened.

  3. Control Control: PASV

    Step 3: Client to Server

    The client asks the server to open a port for a data connection.

  4. Control Control: 227 use this data port

    Step 4: Server to Client

    The reply holds the address and port for the data connection.

  5. Control Control: RETR map42.bin

    Step 5: Client to Server

    The client names the file it wants.

  6. Data Data connection: file bytes

    Step 6: Server to Client

    The file travels on the second connection, separate from the commands.

  7. Control Control: 226 transfer complete

    Step 7: Server to Client

    The control connection reports the end of the transfer.

One connection carries commands; a second connection carries each file.

Publishing the map might use FTP, which separates control and data connections, or SFTP, which transfers files over encrypted SSH. SFTP is different from FTPS, FTP secured with TLS. A web server might use FastCGI to pass requests to a persistent application worker; the player’s side still uses HTTP. Web3 applications may use blockchain-backed records, but a ledger is not a replacement for sockets or real-time match transport. Likewise, Base64 only encodes bytes: an encoded login value has not thereby been encrypted.

With those boundaries separate, return to the controlled local capture. We can now ask which interface, direction, and protocol layer produced each row.

Capture answers “what crossed,” not “why”

Section titled “Capture answers “what crossed,” not “why””

A network trace records bytes and timing at one capture point. It does not contain the sender’s variable names, the receiver’s interpretation, or any record of which UI action caused which packet. That link comes from changing one thing at a time:

  1. capture a quiet baseline;
  2. perform exactly one distinctive local action;
  3. repeat the action with one changed input;
  4. compare both directions and several repetitions;
  5. confirm the candidate fields in the open-source client or server.

Use the course’s local Wesnoth server setup or your own toy client and server. Keep both endpoints inside the lab VM.

A local multiplayer lobby

A local multiplayer lobby: client and server on the same machine.

Start Wireshark, choose the loopback adapter when client and server share the machine, and begin capture before connecting.

Capturing on the wrong interface produces an empty-looking experiment. Traffic to 127.0.0.1 stays on the loopback path rather than crossing the physical Wi-Fi or Ethernet adapter.

The Wireshark interface

The Wireshark interface, where the capture starts.

Filter by the known local port. Wireshark has two filter boxes, and each has its own syntax for the same job:

Display filter (hides rows afterwards)

tcp.port == 15000

Capture filter (never records the rest)

tcp port 15000

A display filter can be changed at any time, because everything was recorded. A capture filter keeps the file small, but a packet it dropped cannot be recovered, so use the display filter while you are still learning what to look for.

For the Wesnoth 1.14.9 lab, keep 15000: that is wesnothd’s default listening port. Launch wesnothd.exe, choose Connect to Server in the game, and enter localhost:15000.

Perform the actions at known times, so each burst of packets can be matched to the action just before it:

00:00 connect
00:02 enter username
00:05 join lobby
00:08 send "hello-17"
00:12 disconnect

A distinctive message such as hello-17 is easier to find than “hi.”

One connection has one four-tuple, and each direction reads it the other way round:

client IP : client port → server IP : server port
server IP : server port → client IP : client port

The client port is often temporary. The server port is the stable listening port.

The server first owns a listening socket on port 15000. Accepting a client creates a separate connected socket while the listener remains available for other clients. The client normally receives an ephemeral local port selected by Windows.

Wireshark’s “Follow TCP Stream” view reassembles TCP bytes for easier inspection.

Following a TCP stream

Follow TCP Stream shows the reassembled bytes of one connection.

Remember: this is still a stream, not necessarily a list of messages. Look for:

  • fixed-size headers;
  • length fields;
  • magic bytes;
  • repeated separators;
  • readable text;
  • compressed-looking regions;
  • request/response pairs.

“Follow TCP Stream” performs reassembly for inspection. Your client still has to handle partial reads: read() may return fewer bytes than requested even when more bytes will arrive later. read_exact is appropriate only after a validated frame length tells you exactly how many bytes belong to the next piece.

Reassembly also chooses an order from sequence numbers and removes retransmitted overlap. Preserve the original packet capture alongside any exported stream fixture so later questions about direction, timing, or retransmission can still be answered.

Save only the bytes for one clearly labeled action. A small binary fixture is excellent for parser tests.

#[test]
fn parses_recorded_local_chat_frame() {
let bytes = include_bytes!("fixtures/local-chat-frame.bin");
let message = parse_frame(bytes).expect("fixture should parse");
assert!(matches!(message, Message::Chat { .. }));
}

Do not store secrets, account tokens, or other people’s traffic in fixtures.

Repeat the same action with exactly one changed input:

Capture A: send "red"
Capture B: send "blue"

Compare lengths and differing byte ranges. If only one region changes, it may contain the text. If the whole payload changes, compression or encryption may be involved.

A server message identified in the stream

A server message identified in the stream.

Add this display filter so Wireshark shows client/server data rather than every TCP acknowledgement:

tcp.port == 15000 && tcp.flags.push == 1

The first client payload in a Wesnoth 1.14.9 connection is exactly four zero bytes:

00 00 00 00

Replay only those four bytes from a tiny TCP client. The local server responds with 41 bytes across the observed replies, proving that the zeros begin protocol negotiation. The next client frame identifies version 1.14.9; the following frame logs in with the chosen username.

After the four-byte frame length, both of those later frames begin with gzip magic bytes 1F 8B. For example, a captured version frame begins:

00 00 00 2F 1F 8B 08 00 ...
└─ length 47 ┘ └─ gzip data

Do the same controlled capture with usernames IEUser and FFFAAAKKKEEE. The second name makes repeated-character compression easier to notice. Put together, the Wesnoth 1.14.9 connection works like this:

target: Wesnoth 1.14.9 + local wesnothd
transport: TCP
server: 127.0.0.1:15000
negotiation: 00 00 00 00
normal frame: u32 big-endian compressed length + gzip(Simple WML)
login order: negotiation → version → username → lobby

A useful frame fixture records:

  • the start of one frame;
  • the field that gives its size, or another reliable delimiter;
  • its direction;
  • one input and the bytes that changed because of it.
Knowledge check

Find message structure

Which capture method best reveals how one local game action is encoded?

Finished Lesson 9.3?

Mark it done and the lesson list shows a beside it. A chapter whose lessons are all done is marked done too. Progress is saved in this browser only.

Chapter 9: 10 lessons

This book grew out of the original Game Hacking Academy by attilathedud and has been rewritten as a beginner-first course. Like the original repository, its source is published under the Apache License 2.0.