Skip to content

Latest commit

 

History

History
57 lines (38 loc) · 1.75 KB

File metadata and controls

57 lines (38 loc) · 1.75 KB

02 Exercises

Exercise 1: Hand-write RESP

Using printf + nc, send these by hand:

printf '*1\r\n$4\r\nPING\r\n' | nc localhost 6380
# -> +PONG\r\n

printf '*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n' | nc localhost 6380
# -> $20\r\n['SET', 'foo', 'bar']\r\n

Checkpoint: The second one echoes the parsed array as a string. We'll replace this with real SET in step 3.

Exercise 2: Inline commands

Real redis-cli also accepts "inline" commands separated by spaces and ended with \r\n:

PING\r\n
SET foo bar\r\n

Extend parse_resp to detect when the first byte is NOT one of +-:$* and parse the line as a space-separated command. (Hint: split on spaces, treat each word as a bulk string.)

Checkpoint: printf 'PING\r\n' | nc localhost 6380 returns +PONG\r\n.

Exercise 3: Test the partial-read path

Send a command one byte at a time:

import socket, time
s = socket.socket()
s.connect(("127.0.0.1", 6380))
frame = b'*1\r\n$4\r\nPING\r\n'
for byte in frame:
    s.sendall(bytes([byte]))
    time.sleep(0.05)
print(s.recv(100))

Checkpoint: The reply is b'+PONG\r\n'. The server reassembled the frame from individual-byte chunks because the parser returned None until the buffer was complete.

Exercise 4: Crash on bad input

Send something that isn't valid RESP and see what happens:

printf 'garbage\r\n' | nc localhost 6380

The server should log a ProtocolError. In production you'd want to drop the connection cleanly instead of letting the exception bubble. Add a try/except in handle_client that closes the socket on ProtocolError and logs the offending bytes.

Checkpoint: The server keeps running and accepts new clients after a bad input. It does not crash the whole process.