2016-02-12 90 views
0

我想用多線程的Python編寫一個非常簡單的web服務器。眼下的代碼看起來像這樣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> 

然而,當我去鍵入localhost:在Chrome 8031/hello.html的,它只是加載永遠說「等待本地主機」。我有一個打印,應該發生每當一個新的消息收到,但它不是打印告訴我服務器沒有正確接收郵件

當我嘗試第二次連接鉻平坦告訴我連接被拒絕當我按ENTER鍵停止服務器似乎退出很好,但後來我得到一個錯誤信息

enter image description here

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

回答

0

在我的代碼中,我在下面的發佈代碼中經歷了幾個錯誤。一般說明是:在服務器上

  • 使用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() 
+0

太謝謝你了!我非常感謝你的幫助 –

1

顯然你正試圖訪問你已經關閉的文件或套接字。

見行:

sock, addr = self._sock.accept() 

您嘗試接受,你已經關閉套接字的請求。

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