multithreading - Python 2.7: streaming HTTP server supporting multiple connections on one port -
i looking standard python 2.7 package providing http server simultaneous streaming connections on same port number.
hey moderators out there, please stop flagging question duplicate of questions want serve in non-streaming ways, one: multithreaded web server in python. no, don't want hack such threadingmixin
merely collects response , returns unit.
in other words, i'm looking standard way following example program -- without writing whole http server myself.
import time, socket, threading sock = socket.socket (socket.af_inet, socket.sock_stream) host = socket.gethostname() port = 8000 sock.bind((host, port)) sock.listen(1) # own http server... oh man, bad style. http = "http/1.1 200 ok\ncontent-type: text/html; charset=utf-8\n\n" class listener(threading.thread): def __init__(self): threading.thread.__init__(self) self.daemon = true # stop python biting ctrl-c self.start() def run(self): conn, addr = sock.accept() conn.send(http) # serve infinite stream = 0 while true: conn.send("%i " % i) time.sleep(0.1) += 1 [listener() in range(100)] time.sleep(9e9)
so first tried:
# run command: # gunicorn -k gevent myapp:app import time def app(environ, start_response): data = b"hello, world!\n" start_response("200 ok", [ ("content-type", "text/plain"), ("content-length", str(len(data))) ]) in range(5): time.sleep(1) yield "hello %i\n" % # https://stackoverflow.com/questions/22739394/streaming-with-gunicorn
but unfortunately doesn't stream, -k gevent
.
update: appears gunicorn trying keepalive, require chunked transfer coding last-chunk
bit. quick grep of sources reveals it's not implementing that. might need fancier http server, or simpler 1 (like first example above, based on socket
) doesn't bother keepalive (which pretty silly large streams anyway).
so tried:
import time import threading import 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 infinite stream = 0 while true: self.wfile.write("%i " % i) time.sleep(0.1) += 1 class listener(threading.thread): def __init__(self, i): threading.thread.__init__(self) self.i = self.daemon = true self.start() def run(self): server_address = ('', 8000+self.i) # how attach of them 8000? httpd = basehttpserver.httpserver(server_address, handler) httpd.serve_forever() [listener(i) in range(100)] time.sleep(9e9)
which pretty good, it's bit annoying have allocate 100 port numbers. require obnoxious client-side redirect browser next available port (well, ok, can hide javascript, it's not elegant. i'd rather write own http server that).
there must clean way basehttpserver
listeners on 1 port, such standard way of setting web server. or maybe gunicorn
or somesuch package can made stream reliably?
the default basehttpserver
settings re-bind new socket on every listener, won't work in linux if listeners on same port. change settings between basehttpserver.httpserver()
call , serve_forever()
call.
the following example launches 100 handler threads on same port, each handler started through 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 infinite stream = 0 while true: self.wfile.write("%i " % i) time.sleep(0.1) += 1 # create 1 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 = self.daemon = true self.start() def run(self): httpd = basehttpserver.httpserver(addr, handler, false) # prevent http server 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) in range(100)] time.sleep(9e9)
Comments
Post a Comment