Ich versuche, einen Multithread-Webserver in Python zu erstellen, aber er antwortet immer nur auf eine Anfrage und ich kann nicht herausfinden, warum. Kannst du mir bitte helfen?
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from SocketServer import ThreadingMixIn
from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
from time import sleep
class ThreadingServer(ThreadingMixIn, HTTPServer):
pass
class RequestHandler(SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/plain')
sleep(5)
response = 'Slept for 5 seconds..'
self.send_header('Content-length', len(response))
self.end_headers()
self.wfile.write(response)
ThreadingServer(('', 8000), RequestHandler).serve_forever()
Check this Post aus Doug Hellmanns Blog.
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import threading
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
message = threading.currentThread().getName()
self.wfile.write(message)
self.wfile.write('\n')
return
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""Handle requests in a separate thread."""
if __== '__main__':
server = ThreadedHTTPServer(('localhost', 8080), Handler)
print 'Starting server, use <Ctrl-C> to stop'
server.serve_forever()
Ich habe ein PIP-Dienstprogramm namens ComplexHTTPServer entwickelt, das eine Multithread-Version von SimpleHTTPServer ist.
Um es zu installieren, müssen Sie nur Folgendes tun:
pip install ComplexHTTPServer
Die Benutzung ist so einfach wie:
python -m ComplexHTTPServer [PORT]
(Standardmäßig ist der Port 8000.)
In python3 können Sie den folgenden Code verwenden (https oder http):
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
import threading
USE_HTTPS = True
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b'Hello world\t' + threading.currentThread().getName().encode() + b'\t' + str(threading.active_count()).encode() + b'\n')
class ThreadingSimpleServer(ThreadingMixIn, HTTPServer):
pass
def run():
server = ThreadingSimpleServer(('0.0.0.0', 4444), Handler)
if USE_HTTPS:
import ssl
server.socket = ssl.wrap_socket(server.socket, keyfile='./key.pem', certfile='./cert.pem', server_side=True)
server.serve_forever()
if __== '__main__':
run()
Sie werden herausfinden, dass dieser Code einen neuen Thread erstellt, um jede Anfrage zu bearbeiten.
Befehl zum Generieren eines Selbstsignierzertifikats:
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
Wenn Sie Flask verwenden, ist dieses Blog großartig.
Hier ist ein weiteres gutes Beispiel für einen HTTP-Server mit mehreren Threads wie SimpleHTTPServer: MultithreadedSimpleHTTPServer on GitHub .
Es ist erstaunlich, wie viele Stimmen diese Lösungen erhalten, die das Streaming unterbrechen. Wenn Streaming später erforderlich sein könnte, sind ThreadingMixIn
und Gunicorn nicht gut, da sie nur die Antwort zusammenfassen und am Ende als Einheit schreiben (was eigentlich nichts bewirkt, wenn Ihr Stream unendlich ist).
Ihr grundlegender Ansatz, BaseHTTPServer
mit Threads zu kombinieren, ist in Ordnung. Die Standardeinstellungen von BaseHTTPServer
binden jedoch einen neuen Socket auf jedem Listener neu, was unter Linux nicht funktioniert, wenn sich alle Listener auf demselben Port befinden. Ändern Sie diese Einstellungen vor dem Aufruf von serve_forever()
. (Genau wie Sie self.daemon = True
In einem Thread setzen müssen, um zu verhindern, dass Strg-C deaktiviert wird.)
Im folgenden Beispiel werden 100 Handler-Threads auf demselben Port gestartet, wobei jeder Handler über BaseHTTPServer
gestartet wird.
import time, threading, socket, SocketServer, BaseHTTPServer
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
if self.path != '/':
self.send_error(404, "Object not found")
return
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
# serve up an infinite stream
i = 0
while True:
self.wfile.write("%i " % i)
time.sleep(0.1)
i += 1
# Create ONE socket.
addr = ('', 8000)
sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(addr)
sock.listen(5)
# Launch 100 listener threads.
class Thread(threading.Thread):
def __init__(self, i):
threading.Thread.__init__(self)
self.i = i
self.daemon = True
self.start()
def run(self):
httpd = BaseHTTPServer.HTTPServer(addr, Handler, False)
# Prevent the HTTP server from re-binding every handler.
# https://stackoverflow.com/questions/46210672/
httpd.socket = sock
httpd.server_bind = self.server_close = lambda self: None
httpd.serve_forever()
[Thread(i) for i in range(100)]
time.sleep(9e9)