Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WebSocket Server (Rust)

A minimal WebSocket server built from scratch to understand the protocol.

What This Project Teaches

  • Protocol upgrade mechanism - HTTP → WebSocket handshake
  • Binary framing - Variable length, opcodes, masking
  • Bidirectional communication - Server can push without client asking

Why WebSocket?

HTTP is request-response:

Client: "Give me data"
Server: "Here's data"
(waits for next request)

WebSocket allows both sides to send anytime:

Client: "Let's upgrade to WebSocket"
Server: "OK, upgraded"
Client: "hello"
Server: "hi"
Server: "here's an update"  ← server initiates!
Server: "another update"
Client: "thanks"

Used for: chat apps, live notifications, multiplayer games, stock tickers.

The Handshake

WebSocket starts as HTTP:

Client sends:
GET / HTTP/1.1
Upgrade: websocket
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

Server responds:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

The Sec-WebSocket-Accept is computed by:

  1. Concatenate client key + magic string 258EAFA5-E914-47DA-95CA-C5AB0DC85B11
  2. SHA-1 hash
  3. Base64 encode

This proves the server understands WebSocket (not encryption, just verification).

WebSocket Frame Structure

After handshake, communication switches to binary frames:

┌─────────┬─────────┬──────────┬─────────────┐
│ Byte 0  │ Byte 1  │Bytes 2-5 │ Rest        │
│FIN+Code │Mask+Len │Mask Key  │ Payload     │
└─────────┴─────────┴──────────┴─────────────┘

Byte 0: 0x81 = FIN(1) + opcode(1 = text) Byte 1: 0x85 = masked(1) + length(5) Bytes 2-5: 4-byte XOR mask key Rest: Masked payload data

Opcodes

  • 1 = text message
  • 2 = binary message
  • 8 = close connection
  • 9 = ping
  • 10 = pong

Why Masking?

Client→Server is always masked. NOT for encryption (mask is visible).

It prevents cache poisoning attacks where malicious bytes could look like HTTP responses to proxy servers.

Run

cargo run

Test

websocat ws://127.0.0.1:8080

Type messages - they echo back!

Project Structure

  • main() - TCP listener, accepts connections
  • handle_client() - HTTP handshake
  • extract_websocket_key() - Parse Sec-WebSocket-Key header
  • compute_accept_key() - SHA1 + Base64 for accept value
  • handle_websocket() - Frame loop after handshake
  • parse_frame() - Decode incoming frames, unmask payload
  • build_frame() - Create outgoing frames (no mask for server)

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages