3

I'm trying to bind multiple servers with python's SocketServer module:

import SocketServer
from SocketServer import BaseRequestHandler

class HTTPSERVER(BaseRequestHandler):

    def handle(self):
        rec = self.request.recv(1024)
        if rec:
           self.request.send('Got something!')

launchme = SocketServer.TCPServer(('', 82),HTTPSERVER)
launchme2 = SocketServer.TCPServer(('', 81),HTTPSERVER)
launchme3 = SocketServer.TCPServer(('', 80),HTTPSERVER)
launchme.serve_forever()
print 'reached first server'
launchme2.serve_forever()
print 'reached second server'
launchme3.serve_forever()
print 'reached third server'

When this script is launched nothing gets printed but all 3 ports are actually open:

root@user:/# netstat -pna|more
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      2751/python     
tcp        0      0 0.0.0.0:81              0.0.0.0:*               LISTEN      2751/python     
tcp        0      0 0.0.0.0:82              0.0.0.0:*               LISTEN      2751/python    

But this script only serve 'Got something!' when the request is made on port 82 (first bind). What is the proper way with the SocketServer module to get all port to work?

Noctis Skytower
  • 21,433
  • 16
  • 79
  • 117
n00bz0r
  • 87
  • 9
  • Serve_forever doesn't return. Run each one in a thread. – Mark Tolonen May 26 '14 at 15:58
  • When you call `serve_forever()` it will run undefinitely and won't resume the execution of the script. Check this other answer http://stackoverflow.com/questions/268629/how-to-stop-basehttpserver-serve-forever-in-a-basehttprequesthandler-subclass – Havenard May 26 '14 at 15:59

2 Answers2

4

server_forever handles requests until an explicit shutdown() request.

Once launchme.serve_forever() called, the next ones will not be called. You need to call them in threads or in separated processes.

import SocketServer
from SocketServer import BaseRequestHandler
import threading

class HTTPSERVER(BaseRequestHandler):

    def handle(self):
        rec = self.request.recv(1024)
        if rec:
           self.request.send('Got something!')

launchme = SocketServer.TCPServer(('', 82),HTTPSERVER)
launchme2 = SocketServer.TCPServer(('', 81),HTTPSERVER)
launchme3 = SocketServer.TCPServer(('', 80),HTTPSERVER)
t1 = threading.Thread(target=launchme.serve_forever)
t2 = threading.Thread(target=launchme2.serve_forever)
t3 = threading.Thread(target=launchme3.serve_forever)
for t in t1, t2, t3: t.start()
for t in t1, t2, t3: t.join()
falsetru
  • 357,413
  • 63
  • 732
  • 636
0

I'm also trying to do the same thing and the socketserver documentation also mentions the selectors package to accomplish this goal (if I understand correctly), when describing the fileno() method of the BaseServer class:

Return an integer file descriptor for the socket on which the server is listening. This function is most commonly passed to selectors, to allow monitoring multiple servers in the same process.

However, I have tried for some hours but I cannot get a working piece of code with such approach.

charlie80
  • 806
  • 1
  • 7
  • 17