[英]Web Server Issue with Concurrency
我是一名Python新手,我想實現一個可以處理多線程的簡單Web服務器。 如果我不對conn.close()
行添加注釋,則一切正常。 如果我對conn.close()
進行注釋,則會出現問題。 客戶端可以在第一個請求后成功獲得響應,但是當我刷新網頁時,瀏覽器將無法接收響應。 有誰能告訴我如何解決這個問題? 我的代碼有問題嗎?
import socket
import threading
import time
class MyServer:
def __init__(self, port, doc_root):
self.port = port
self.doc_root = doc_root
self.host = "localhost"
def run(self):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as soc:
soc.bind((self.host, self.port))
soc.listen(5)
req = b''
while True:
conn, addr = soc.accept()
threading.Thread(target=self.handle_connection, args=(conn, addr)).start()
def handle_connection(self, conn, addr):
assert isinstance(conn, socket.socket)
req = b''
while b'\r\n\r\n' not in req:
req += conn.recv(1024)
print(addr)
print(req.decode())
time.sleep(0.5)
conn.sendall(b'HTTP/1.1 200 OK\r\n\r\nHello World')
print(addr, 'response sent')
# conn.close()
if __name__ == '__main__':
input_port = 8006
input_doc_root = r'/'
server = MyServer(input_port, input_doc_root)
server.run()
您需要conn.close()
因為在沒有服務器關閉連接的情況下刷新瀏覽器會導致該請求沿着相同的連接發送。 發送一個響應后,句柄結束; 在代碼中的第一次請求-響應對話之后,根本沒有讀取和寫入該套接字的信息。
附帶一提,至少在我測試過的瀏覽器上,我在客戶端省略conn.close()
還有一些問題。 由於您不告訴客戶什么時候可以停止從其一側的套接字讀取數據,因此即使渲染完整的響應后,FF也會繼續讀取其端點。
如果將recv
和sendall
置於某個循環中,並向客戶端提示何時完全接收到數據,則它將起作用:
def handle_connection(self, conn, addr):
assert isinstance(conn, socket.socket)
while conn:
req = b''
while b'\r\n\r\n' not in req:
req += conn.recv(1024)
print(addr)
print(req.decode())
time.sleep(0.5)
# Note Content-Lenght in the 'header' below
# to let the clients know when to stop reading
conn.sendall(b'HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nHello World')
print(addr, 'response sent')
# conn.close()
但是,發送響應后關閉連接是正確的做法,恕我直言。 您不能依靠客戶端始終正確地關閉連接,因此您可能會浪費資源以有效地進行過時的會話。 通過上面概述的解決方案,線程傾向於停留一段時間,基本上什么也沒等待。
最后,HTTP是無狀態的,因此除了發送響應之外,維持連接沒有任何意義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.