2012-12-30 22 views
37

私は、PythonでマルチスレッドWebサーバーを作成しようとしていますが、一度に1つの要求にしか応答せず、理由を特定できません。私を助けてくれますか?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() 
+0

ノンブロッキングソケットを使用すると、何千ものクライアントをサーバーすることができます。単一のリクエストごとにスレッドを作成する必要はありません。 –

+0

@ shiplu.mokadd.imあなたはポストをお願いします..あなたの助けが高く評価されるでしょう –

+0

@パイロットここでは2つのものが必要です。 'select()'とノンブロッキングです。 Pythonには[socket](http://docs.python.org/2/library/socket.html)ライブラリがあります。 IBMは、select()を使用したソケット・プログラミングについていくつかの[良い記事](https://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzab6xnonblock.htm)を取得しました。 –

答えて

56

Doug Hellmannのブログからthisの投稿を確認してください。

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

'ThreadingMixIn'はスーパークラスリストの' HTTPServer'の前に来なければならないことに注意してください。そうでないとうまくいきません。 –

+0

すごい! +1 –

+0

詳細な例は[Python3 docs](https://docs.python.org/3.5/library/socketserver.html#asynchronous-mixins)を参照してください。 – Eido95

3

これは、マルチスレッドのSimpleHTTPServerのようなHTTPサーバーの別の良い例です:MultithreadedSimpleHTTPServer on GitHub

+1

+1、これはこのスクリプトの最初の作者が採用したものです(https://kdecherf.com/blog/2012/07/29/multithreaded-python-simple- http-server/ – technomalogical

+0

これはストリーミングされません。 'BaseHTTPServer'を使ったよりよいアプローチは次の通りです:https://stackoverflow.com/questions/46210672/ –

1

私はComplexHTTPServerというPIPユーティリティを開発しました。このユーティリティは、SimpleHTTPServerのマルチスレッドバージョンです。それをインストールするには

、すべてを行う必要がある:

pip install ComplexHTTPServer 

それは同じくらい簡単です使用:

python -m ComplexHTTPServer [PORT] 

(デフォルトでは、ポートは8000です)

+0

私はあなたの答えをアップアップしています。なぜなら、ストリーミングが必要ない場合には他の答えと同様に動作するからです。 –

+0

あなたの答えははるかに簡潔でした! –

1

ストリーミングを破るこれらのソリューションがどれだけ多くの票を得ているのは驚くべきことです。ストリーミングが必要な場合は、ThreadingMixInとgunicornは応答を収集して最後に単位として書き込みます(ストリームが無限であれば実際には何もしません)。

BaseHTTPServerとスレッドを組み合わせる基本的な方法は問題ありません。しかし、デフォルトのBaseHTTPServerの設定では、すべてのリスナーに新しいソケットが再バインドされます。リスナーがすべて同じポートにある場合、Linuxでは機能しません。 serve_forever()コールの前にこれらの設定を変更してください。

次の例では、同じハンドラスレッドを同じポート上で起動し、各ハンドラは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) 
関連する問題