Address reuse in python’s SocketServer

Hello, World! This is my first technical post, I hope it’s useful to someone out there!

I am working on a very small tool that I need to for a proof of concept. It’s basically a small TCP server in python.
After creating a small skeleton using SocketServer, I found that the server it self works fine with no problem.

However, if I try to stop and start the server again to test any modifications, I get a random “socket.error: [Errno 98] Address already in use” error. This happens only if a client has already connected to the server.

Checking with netstat and ps, I found that although the process it self is no longer running, the socket is still listening on the port with status “TIME_WAIT”. Basically the OS  waits for a while to make sure this connection has no remaining packets on the way.

My good friend mux mentioned that I should probably set the socket option “SO_REUSEADDR” to avoid this issue.

The man socket(7) says about this:

SO_REUSEADDR

Indicates that the rules used in validating addresses supplied in a bind(2) call should allow reuse of local addresses.  For AF_INET sockets this means that a socket may bind, except when there is an active listening socket bound to the address.  When the listening socket is bound to INADDR_ANY with a specific port then it is not possible to bind to this port for any local address.  Argument is an integer boolean flag.

When using the pure socket module, you can simply set this option using:

import socket

s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

 

However, you don’t need to this in SocketServer. SocketServer.TCPServer allows you to set by setting a simple variable. Here is a working example:

#! /usr/bin/env python
import socket
import SocketServer

class MyServer(SocketServer.StreamRequestHandler):

def handle(self):

self.wfile.write("Hi! I am echo!\n")

while True:

data = self.rfile.readline().strip()
if not data: break
self.wfile.write(">>%s\n" % data)

if __name__ == "__main__":

host, port = "localhost", 10000
# Setting allow_resue_address to True.
SocketServer.TCPServer.allow_reuse_address = True
server = SocketServer.TCPServer((host, port), MyServer)
server.serve_forever()

 

This is just a simple example of how to use it. You can check the last link in the resources for a more complex example with threading support.

Resources:

http://linux.die.net/man/7/socket
http://docs.python.org/library/socket.html
http://docs.python.org/library/socketserver.html
http://code.activestate.com/lists/python-list/222584/
http://www.technovelty.org/code/python/socketserver.html

3 Comments

  1. So you finally figured it out :D , your post may save some tormented spirit one day. Just keep writing.

Leave a Reply

Your email address will not be published.