Question

J'écris un petit serveur Web en Python, en utilisant BaseHTTPServer et une sous-classe personnalisée de BaseHTTPServer.BaseHTTPRequestHandler.Est-il possible de faire écouter cette écoute sur plusieurs ports ?

Ce que je fais maintenant :

class MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
  def doGET
  [...]

class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): 
    pass

server = ThreadingHTTPServer(('localhost', 80), MyRequestHandler)
server.serve_forever()
Était-ce utile?

La solution

Bien sûr;démarrez simplement deux serveurs différents sur deux ports différents dans deux threads différents qui utilisent chacun le même gestionnaire.Voici un exemple complet et fonctionnel que je viens d'écrire et de tester.Si vous exécutez ce code, vous pourrez obtenir une page Web Hello World à la fois http://localhost:1111/ et http://localhost:2222/

from threading import Thread
from SocketServer import ThreadingMixIn
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write("Hello World!")

class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
    pass

def serve_on_port(port):
    server = ThreadingHTTPServer(("localhost",port), Handler)
    server.serve_forever()

Thread(target=serve_on_port, args=[1111]).start()
serve_on_port(2222)

mise à jour:

Cela fonctionne également avec Python 3 mais trois lignes doivent être légèrement modifiées :

from socketserver import ThreadingMixIn
from http.server import HTTPServer, BaseHTTPRequestHandler

et

self.wfile.write(bytes("Hello World!", "utf-8"))

Autres conseils

Je dirais que le threading pour quelque chose d'aussi simple est exagéré.Il vaut mieux utiliser une forme de programmation asynchrone.

Voici un exemple utilisant Tordu:

from twisted.internet import reactor
from twisted.web import resource, server

class MyResource(resource.Resource):
    isLeaf = True
    def render_GET(self, request):
        return 'gotten'

site = server.Site(MyResource())

reactor.listenTCP(8000, site)
reactor.listenTCP(8001, site)
reactor.run()

Je pense également qu'il semble beaucoup plus propre que chaque port soit géré de la même manière, au lieu que le thread principal gère un port et qu'un thread supplémentaire gère l'autre.Cela peut sans doute être corrigé dans l'exemple de thread, mais vous utilisez alors trois threads.

Pas facilement.Vous pouvez avoir deux instances ThreadingHTTPServer, écrire votre propre fonction serve_forever() (ne vous inquiétez pas, ce n'est pas une fonction compliquée).

La fonction existante :

def serve_forever(self, poll_interval=0.5):
    """Handle one request at a time until shutdown.

    Polls for shutdown every poll_interval seconds. Ignores
    self.timeout. If you need to do periodic tasks, do them in
    another thread.
    """
    self.__serving = True
    self.__is_shut_down.clear()
    while self.__serving:
        # XXX: Consider using another file descriptor or
        # connecting to the socket to wake this up instead of
        # polling. Polling reduces our responsiveness to a
        # shutdown request and wastes cpu at all other times.
        r, w, e = select.select([self], [], [], poll_interval)
        if r:
            self._handle_request_noblock()
    self.__is_shut_down.set()

Notre remplacement serait donc quelque chose comme :

def serve_forever(server1,server2):
    while True:
        r,w,e = select.select([server1,server2],[],[],0)
        if server1 in r:
            server1.handle_request()
        if server2 in r:
            server2.handle_request()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top