【问题标题】:Simple Multithreaded Web Server in PythonPython 中的简单多线程 Web 服务器
【发布时间】:2025-12-31 17:25:03
【问题描述】:

我正在尝试使用 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 文件,用于从 localhost 测试它

<!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 停止服务器时,它似乎退出正常,但随后我收到一条错误消息

我很沮丧,不知道如何调试它,所以任何帮助都将不胜感激!

【问题讨论】:

    标签: python multithreading webserver


    【解决方案1】:

    显然您正在尝试访问已关闭的文件或套接字。

    见行:

    sock, addr = self._sock.accept()
    

    您正在尝试使用已关闭的套接字接受请求。

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

    【讨论】:

      【解决方案2】:

      您的代码中有几个错误,我在下面发布的代码中遇到了这些错误。一般注意事项是:

      • 在服务器上使用 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()
      

      【讨论】:

      • 非常感谢!我非常感谢您的所有帮助
      最近更新 更多