简体   繁体   English

Python中的简单多线程Web服务器

[英]Simple Multithreaded Web Server in Python

I'm trying to write a really simple web server with Python that is multithreaded. 我正在尝试使用多线程的Python编写一个非常简单的Web服务器。 Right now the code looks like this 现在的代码看起来像这样

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

My strategy is to start the web server in the main method and then start connection threads from the server thread. 我的策略是使用main方法启动Web服务器,然后从服务器线程启动连接线程。 I have a simple helloworld html file in the same directory which I'm using to test it from localhost 我在用于从本地主机对其进行测试的同一目录中有一个简单的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>

However, when I go to type localhost:8031/hello.html in Chrome, it just loads forever saying "waiting for localhost". 但是,当我在Chrome中输入localhost:8031 / hello.html时,它将永远加载并显示“正在等待localhost”。 I have a print that is supposed to happen whenever a new message is received but it's not printing which tells me the server is not receiving messages properly 我有一个应该在收到新消息时发生的打印,但它没有打印,这表明服务器没有正确接收消息

When I try to connect a second time Chrome flat out tells me the connection was refused and when I press enter to stop the server it seems to quit fine but then I get an error message 当我第二次尝试连接时,Chrome断断续续地告诉我连接被拒绝,并且当我按Enter键以停止服务器时,它似乎退出了,但是却收到错误消息

在此处输入图片说明

I'm frustrated and not sure how to debug this so any help would be greatly appreciated! 我很沮丧,不知道如何调试它,所以任何帮助将不胜感激!

Apparently you are trying to access a file or socket you already closed. 显然,您正在尝试访问已关闭的文件或套接字。

See line: 见行:

sock, addr = self._sock.accept()

You are trying to accept a request with a socket that you already closed. 您正在尝试使用已关闭的套接字接受请求。

Check the file descriptor(could be a socket) that is usually represented as a number. 检查通常以数字表示的文件描述符(可以是套接字)。

You have several errors in your code that I went through in the posted code below. 您的代码中有几个错误,我在下面的发布代码中遇到过。 General notes are: 一般说明是:

  • use SO_REUSEADDR on the server so you don't have to wait to execute a second time 在服务器上使用SO_REUSEADDR,因此您不必等待第二次执行
  • shutdown a socket before close or the underlying socket may stay open, hanging your browser 在关闭之前关闭套接字,否则基础套接字可能保持打开状态,从而挂起浏览器
  • you close client sockets in two places... catch errors so that you can close them all 您在两个位置关闭客户端套接字...捕获错误,以便您可以全部关闭它们
  • that 'Bad file descriptor' error is a good thing. “错误的文件描述符”错误是一件好事。 It happened because you closed the socket and it lets your server thread know its time to terminate. 发生这种情况是因为您关闭了套接字,它使您的服务器线程知道终止时间。 You could catch it an exit gracefully if you want 您可以根据需要优雅地退出它
  • you need a better way to deal with background threads. 您需要一种更好的方式来处理后台线程。 Right now your list just grows forever and over time most will be stale. 现在,您的列表将永远增长,随着时间的推移,大多数列表将变得陈旧。 I marked them as daemon threads so that the program would terminate at the end, but you need something else. 我将它们标记为守护程序线程,以便该程序在结尾处终止,但是您还需要其他内容。

Fixing up the errors I came up with 解决我提出的错误

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