簡體   English   中英

Python中的簡單多線程Web服務器

[英]Simple Multithreaded Web Server in Python

我正在嘗試使用多線程的Python編寫一個非常簡單的Web服務器。 現在的代碼看起來像這樣

from socket import *
import threading
import time

class serverThread(threading.Thread):
    def __init__(self, serverPort):
        threading.Thread.__init__(self)
        self.serverPort = serverPort
        self.serverSocket = socket(AF_INET, SOCK_STREAM)
        self.connectionThreads = []
    def run(self):
        self.serverSocket.bind(('', self.serverPort))
        self.serverSocket.listen(1)
        while True:
            #Establish the connection
            print 'Ready to serve...'
            connectionSocket = self.serverSocket.accept()
            message = connectionSocket.recv(1024) #Get message
            print "Message recieved, opening new thread"
            self.connectionThreads.append(connectionThread())
            self.connectionThreads[len(connectionThreads)-1].start()
    def close(self):
        for t in self.connectionThreads:
            t.close()
        self.serverSocket.close()

class connectionThread (threading.Thread):
    def __init__(self, connSocket, message):
        threading.Thread.__init__(self)
        self.connSocket = connSocket
        self.message = message
    def run(self):
        try:
            filename = self.message.split()[1] #Getting requested HTML page
            f = open(filename[1:]) #Opening data stream from HTML
            outputdata = f.read() #Reading HTML page
            f.close() #Closing data stream from HTML
            self.connSocket.send("HTTP/1.0 200 OK\r\n") #Send one HTTP header line into socket
            for i in range(0, len(outputdata)): #Send the content of the requested file to the client
                self.connSocket.send(outputdata[i])
        except IOError: #Triggered if user requests bad link
            self.connSocket.send("404 Not Found") #Send response message for file not found
        finally:
            self.connSocket.close()

def main():
    server = serverThread(8031)
    server.start()
    end = raw_input("Press enter to stop server...")
    server.close()
    print "Program complete"

main()

我的策略是使用main方法啟動Web服務器,然后從服務器線程啟動連接線程。 我在用於從本地主機對其進行測試的同一目錄中有一個簡單的helloworld html文件

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    HELLO WORLD!
</body>
</html>

但是,當我在Chrome中輸入localhost:8031 / hello.html時,它將永遠加載並顯示“正在等待localhost”。 我有一個應該在收到新消息時發生的打印,但它沒有打印,這表明服務器沒有正確接收消息

當我第二次嘗試連接時,Chrome斷斷續續地告訴我連接被拒絕,並且當我按Enter鍵以停止服務器時,它似乎退出了,但是卻收到錯誤消息

在此處輸入圖片說明

我很沮喪,不知道如何調試它,所以任何幫助將不勝感激!

顯然,您正在嘗試訪問已關閉的文件或套接字。

見行:

sock, addr = self._sock.accept()

您正在嘗試使用已關閉的套接字接受請求。

檢查通常以數字表示的文件描述符(可以是套接字)。

您的代碼中有幾個錯誤,我在下面的發布代碼中遇到過。 一般說明是:

  • 在服務器上使用SO_REUSEADDR,因此您不必等待第二次執行
  • 在關閉之前關閉套接字,否則基礎套接字可能保持打開狀態,從而掛起瀏覽器
  • 您在兩個位置關閉客戶端套接字...捕獲錯誤,以便您可以全部關閉它們
  • “錯誤的文件描述符”錯誤是一件好事。 發生這種情況是因為您關閉了套接字,它使您的服務器線程知道終止時間。 您可以根據需要優雅地退出它
  • 您需要一種更好的方式來處理后台線程。 現在,您的列表將永遠增長,隨着時間的推移,大多數列表將變得陳舊。 我將它們標記為守護程序線程,以便該程序在結尾處終止,但是您還需要其他內容。

解決我提出的錯誤

from socket import *
import threading
import time

class serverThread(threading.Thread):
    def __init__(self, serverPort):
        threading.Thread.__init__(self)
        self.serverPort = serverPort
        self.serverSocket = socket(AF_INET, SOCK_STREAM)
        self.serverSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.connectionThreads = []
    def run(self):
        self.serverSocket.bind(('', self.serverPort))
        self.serverSocket.listen(1)
        while True:
            #Establish the connection
            print 'Ready to serve...'
            connectionSocket,addr = self.serverSocket.accept()
            message = connectionSocket.recv(1024) #Get message
            print "Message recieved, opening new thread"
            self.connectionThreads.append(connectionThread(connectionSocket, message))
            self.connectionThreads[-1].daemon = 1
            self.connectionThreads[-1].start()
    def close(self):
        for t in self.connectionThreads:
            try:
                t.connSocket.shutdown(SHUT_RDWR)
                t.connSocket.close()
            except socket.error:
                pass
        self.serverSocket.shutdown(SHUT_RDWR)
        self.serverSocket.close()

class connectionThread (threading.Thread):
    def __init__(self, connSocket, message):
        threading.Thread.__init__(self)
        self.connSocket = connSocket
        self.message = message
    def run(self):
        try:
            filename = self.message.split()[1] #Getting requested HTML page
            f = open(filename[1:]) #Opening data stream from HTML
            outputdata = f.read() #Reading HTML page
            f.close() #Closing data stream from HTML
            self.connSocket.send("HTTP/1.0 200 OK\r\n") #Send one HTTP header line into socket
            for i in range(0, len(outputdata)): #Send the content of the requested file to the client
                self.connSocket.send(outputdata[i])
        except IOError: #Triggered if user requests bad link
            self.connSocket.send("404 Not Found") #Send response message for file not found
        finally:
            self.connSocket.shutdown(SHUT_RDWR)
            self.connSocket.close()

def main():
    server = serverThread(8031)
    server.daemon = 1
    server.start()
    end = raw_input("Press enter to stop server...")
    server.close()
    print "Program complete"

main()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM