Как мне написать HTTP-сервер Python для прослушивания нескольких портов?

StackOverflow https://stackoverflow.com/questions/60680

  •  09-06-2019
  •  | 
  •  

Вопрос

Я пишу небольшой веб-сервер на Python, используя BaseHTTPServer и собственный подкласс BaseHTTPServer.BaseHTTPRequestHandler.Можно ли заставить это прослушивать более чем один порт?

Что я делаю сейчас:

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

class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): 
    pass

server = ThreadingHTTPServer(('localhost', 80), MyRequestHandler)
server.serve_forever()
Это было полезно?

Решение

Конечно;просто запустите два разных сервера на двух разных портах в двух разных потоках, каждый из которых использует один и тот же обработчик.Вот полный рабочий пример, который я только что написал и протестировал.Если вы запустите этот код, вы сможете получить веб-страницу Hello World как на http://локальный хост:1111/ и http://локальный хост: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)

обновлять:

Это также работает с Python 3, но необходимо немного изменить три строки:

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

и

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

Другие советы

Я бы сказал, что использование потоков для чего-то такого простого — это излишество.Вам лучше использовать какую-либо форму асинхронного программирования.

Вот пример использования витой:

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()

Я также думаю, что гораздо чище будет, если каждый порт будет обрабатываться одинаково, вместо того, чтобы основной поток обрабатывал один порт, а дополнительный поток - другой.Возможно, это можно исправить в примере с потоками, но тогда вы используете три потока.

Не легко.У вас может быть два экземпляра ThreadingHTTPServer, и вы можете написать свою собственную функцию «serve_forever()» (не волнуйтесь, это несложная функция).

Существующая функция:

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()

Наша замена будет выглядеть примерно так:

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()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top