Simple Multithreaded Web Server in Python

时间:2016-02-12 21:57:46

标签: python multithreading webserver

I'm trying to write a really simple web server with Python that is multithreaded. Right now the code looks like this

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        InitializeComponent();
        MyVisualStateGroup.CurrentStateChanged += (s, e) =>
            HandleState(AdaptiveVisualStateGroup.CurrentState);
    }

    private void HandleState(VisualState currentState)
    {
        // TODO
    }
}

My strategy is to start the web server in the main method and then start connection threads from the server thread. I have a simple helloworld html file in the same directory which I'm using to test it from localhost

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

However, when I go to type localhost:8031/hello.html in Chrome, it just loads forever saying "waiting for 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

enter image description here

I'm frustrated and not sure how to debug this so any help would be greatly appreciated!

2 个答案:

答案 0 :(得分:1)

Apparently you are trying to access a file or socket you already closed.

See line:

var newList = list.Select(x => new HashSet<int>(x))
               .Distinct(HashSet<int>.CreateSetComparer()).ToList();

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.

答案 1 :(得分:0)

我在您的代码中有几个错误,我在下面的发布代码中经历过。一般说明如下:

  • 在服务器上使用SO_REUSEADDR,这样您就不必再等待第二次执行
  • 关闭前关闭套接字或底层套接字可能保持打开状态,挂起浏览器
  • 你在两个地方关闭客户端套接字......捕获错误,以便你可以关闭它们
  • 那个&#39;错误的文件描述符&#39;错误是件好事。之所以发生这种情况,是因为您关闭了套接字,它让您的服务器线程知道终止的时间。如果你想要
  • ,你可以优雅地抓住它
  • 您需要一种更好的方式来处理后台线程。现在你的名单只是永远增长,随着时间的推移,大多数都会陈旧。我将它们标记为守护程序线程,以便程序在最后终止,但是你还需要其他东西。

解决我提出的错误

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