lucasrodesg
lucasrodesg

Reputation: 718

Run more than one server using python

I am basically trying to run two servers using a simple script. I have used the solutions from here, there and others. For instance in the example below I am trying to host two directories in ports 8000 and 8001.

import http.server
import socketserver
import os
import multiprocessing


def run_webserver(path, PORT):
    os.chdir(path)
    Handler = http.server.SimpleHTTPRequestHandler
    httpd = socketserver.TCPServer(('0.0.0.0', PORT), Handler)

    httpd.serve_forever()

    return


if __name__ == '__main__':

    # Define "services" directories and ports to use to host them
    server_details = [
        ("path/to/directory1", 8000),
        ("path/to/directory2", 8001)
    ]

    # Run servers
    servers = []
    for s in server_details: 
        p = multiprocessing.Process(
            target=run_webserver, 
            args=(s[0], s[1])
            )
        servers.append(p)  

    for server in servers:
        server.start()

    for server in servers:
        server.join()

Once I execute the code below it all works fine and I can access both directories using http://localhost:8000 and http://localhost:8001. However, when I exit the script using Ctrl+C and then try to run the script again I get the following error:

 Traceback (most recent call last):                                                                                     
 "/home/user/anaconda3/lib/python3.6/multiprocessing/process.py", line 258, in _bootstrap           
        self.run()                                                                                                         
      File "/home/user/anaconda3/lib/python3.6/multiprocessing/process.py", line 93, in run                   
        self._target(*self._args, **self._kwargs)                                                                          
      File "repos/scripts/webhosts.py", line 12, in run_webserver                                                          
      File "/home/user/anaconda3/lib/python3.6/socketserver.py", line 453, in __init__                        
        self.server_bind()                                                                                                 
      File "/home/user/anaconda3/lib/python3.6/socketserver.py", line 467, in server_bind                     
        self.socket.bind(self.server_address)                                                                              
    OSError: [Errno 98] Address already in use 

This error only pops up if I actually access the server when running. If I do not access to it, I can re-run the script... From the error message it looks like there is something still accessing the server when typing lsof -n -i4TCP:8000 and lsof -n -i4TCP:8001 I don't get anything... And after a while this error stops appearing and I can actually run the script.

Upvotes: 2

Views: 1802

Answers (2)

yorodm
yorodm

Reputation: 4461

Expanding on my comment:

In a previous edit OP registered an exit handler atexit.register(exit_handler). The question is, does it cleans your systems resources (a.k.a open sockets)?

If your program exits without closing the sockets (because you interrupted it with Ctrl+C) it make take some time for the OS clean up the sockets (cause they're in TIME_WAIT state), you can read about TIME_WAIT and how to avoid it in here.

Using exit handlers is a good way to avoid this

import atexit
atexit.register(clean_sockets)

def clean_sockets():
    mysocket.server_close() #

Upvotes: 0

Joe Iddon
Joe Iddon

Reputation: 20434

Before starting the server, add:

socketserver.TCPServer.allow_reuse_address = True

or change that attribute of the instance, again before calling serve_forever():

htttp.allow_reuse_address = True

Documentation reference:

BaseServer.allow_reuse_address

Whether the server will allow the reuse of an address. This defaults to False, and can be set in subclasses to change the policy.

Upvotes: 2

Related Questions