python中的多线程Web服务器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14088294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multithreaded web server in python
提问by user1937459
I'm trying to create multithreaded web server in python, but it only responds to one request at a time and I can't figure out why. Can you help me, please?
我正在尝试在 python 中创建多线程 Web 服务器,但它一次只响应一个请求,我不知道为什么。你能帮我吗?
#!/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()
采纳答案by root
Check thispost from Doug Hellmann's 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 __name__ == '__main__':
server = ThreadedHTTPServer(('localhost', 8080), Handler)
print 'Starting server, use <Ctrl-C> to stop'
server.serve_forever()
回答by ViCky
I have developed a PIP Utility called ComplexHTTPServerthat is a multi-threaded version of SimpleHTTPServer.
我开发了一个名为ComplexHTTPServer的 PIP 实用程序,它是 SimpleHTTPServer 的多线程版本。
To install it, all you need to do is:
要安装它,您需要做的就是:
pip install ComplexHTTPServer
Using it is as simple as:
使用它很简单:
python -m ComplexHTTPServer [PORT]
(By default, the port is 8000.)
(默认情况下,端口为 8000。)
回答by personal_cloud
It's amazing how many votes these solutions that break streaming are getting. If streaming might be needed down the road, then ThreadingMixInand gunicorn are no good because they just collect up the response and write it as a unit at the end (which actually does nothing if your stream is infinite).
令人惊讶的是,这些打破流媒体的解决方案获得了多少票。如果以后可能需要流式传输,那么ThreadingMixIngunicorn 就不好用了,因为它们只是收集响应并将其作为一个单元写在最后(如果您的流是无限的,实际上什么都不做)。
Your basic approach of combining BaseHTTPServerwith threads is fine. But the default BaseHTTPServersettings re-bind a new socket on every listener, which won't work in Linux if all the listeners are on the same port. Change those settings before the serve_forever()call. (Just like you have to set self.daemon = Trueon a thread to stop ctrl-C from being disabled.)
您BaseHTTPServer与线程结合的基本方法很好。但是默认BaseHTTPServer设置会在每个监听器上重新绑定一个新的套接字,如果所有监听器都在同一个端口上,这在 Linux 中将不起作用。在serve_forever()通话前更改这些设置。(就像您必须self.daemon = True在线程上设置以阻止 ctrl-C 被禁用一样。)
The following example launches 100 handler threads on the same port, with each handler started through BaseHTTPServer.
以下示例在同一端口上启动 100 个处理程序线程,每个处理程序通过BaseHTTPServer.
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)
回答by g10guang
In python3, you can use the code below (https or http):
在python3中,您可以使用以下代码(https或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 __name__ == '__main__':
run()
You will figure out this code will create a new thread to deal with every request.
你会发现这段代码会创建一个新线程来处理每个请求。
Command below to generate self-sign certificate:
以下命令生成自签名证书:
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
If you are using Flask, this blogis great.
如果您使用 Flask,这个博客很棒。
回答by cocajoo cheng
A multithreaded https server in python3.7
python3.7中的多线程https服务器
from http.server import BaseHTTPRequestHandler, HTTPServer
from socketserver import ThreadingMixIn
import threading
import ssl
hostName = "localhost"
serverPort = 8080
class MyServer(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes("<html><head><title>https://pythonbasics.org</title></head>", "utf-8"))
self.wfile.write(bytes("<p>Request: %s</p>" % self.path, "utf-8"))
self.wfile.write(bytes("<p>Thread: %s</p>" % threading.currentThread().getName(), "utf-8"))
self.wfile.write(bytes("<p>Thread Count: %s</p>" % threading.active_count(), "utf-8"))
self.wfile.write(bytes("<body>", "utf-8"))
self.wfile.write(bytes("<p>This is an example web server.</p>", "utf-8"))
self.wfile.write(bytes("</body></html>", "utf-8"))
class ThreadingSimpleServer(ThreadingMixIn,HTTPServer):
pass
if __name__ == "__main__":
webServer = ThreadingSimpleServer((hostName, serverPort), MyServer)
webServer.socket = ssl.wrap_socket(webServer.socket, keyfile='./privkey.pem',certfile='./certificate.pem', server_side=True)
print("Server started http://%s:%s" % (hostName, serverPort))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server stopped.")
you can test it in a browser: https://localhost:8080the running result is:
enter image description here
enter image description hereremind that you can generate your own keyfile and certificate use
可以在浏览器中测试:https://localhost:8080运行结果为:
在此
输入图片描述 在此输入图片描述提醒您可以生成自己的密钥文件和证书使用
$openssl req -newkey rsa:2048 -keyout privkey.pem -x509 -days 36500 -out certificate.pem
To learn details about creating self-signed certificate with openssl:https://www.devdungeon.com/content/creating-self-signed-ssl-certificates-openssl
要了解有关使用 openssl 创建自签名证书的详细信息:https: //www.devdungeon.com/content/creating-self-signed-ssl-certificates-openssl

