How to write a memcached server in less than 50 lines of code

Step 1: Figuring out how to build a web server

import socketserverclass MyTCPHandler(socketserver.BaseRequestHandler):
"""
The request handler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()

Step 2: Reading about the protocol

set tutorialspoint 0 900 9
memcached
STORED
get tutorialspoint
VALUE tutorialspoint 0 9
Memcached
END
  • key − It is the name of the key by which data is stored and retrieved from Memcached.
  • flags − It is the 32-bit unsigned integer that the server stores with the data provided by the user, and returns along with the data when the item is retrieved.
  • exptime − It is the expiration time in seconds. 0 means no delay. If exptime is more than 30 days, Memcached uses it as a UNIX timestamp for expiration.
  • bytes − It is the number of bytes in the data block that needs to be stored. This is the length of the data that needs to be stored in Memcached.
  • noreply (optional) − It is a parameter that informs the server not to send any reply.
  • value − It is the data that needs to be stored. The data needs to be passed on the new line after executing the command with the above options.

Step 3: Set up the environment

brew install memcached
from pymemcache.client import base
client = base.Client(('localhost', 11211))
client.set('some_key', 'some value')
print(client.get('some_key'))

Step 4: Let’s code!

  1. Using a StreamRequestHandler instead of a standard TCP server — this is to allow us to use the readline command, which reads a line from a stream until a \r\n sequence has been read. This is useful for textual protocols such as memcached, where this is something that is expected from us (e.g. read one line exactly, as opposed to read 4 bytes for example). The socketserver Python docs do contain information about this handler.
  2. Using a main loop in conjunction with a peek command — texual web servers also expect that you read all lines which are in the buffer for each connection being made, which is why a while True loop is necessary. However, we don’t want to keep the connection hanging if there’s nothing to read as part of a new sequence, so we can use peek to determine if there’s anything to read right now.

Summary

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store