2010-01-14 92 views
9

我正在Python中編寫客戶端/服務器應用程序,我發現有必要爲客戶端的每個請求獲取到服務器的新連接。我的服務器只是從TCPServer繼承而來,我從BaseRequestHandler繼承來完成我的處理。我沒有在處理程序中的任何地方調用self.request.close(),但不知何故服務器似乎掛在我的客戶端上。這是怎麼回事?Python的SocketServer中的TCPServer + BaseRequestHandler在每次調用handle()後關閉套接字嗎?

+0

這是UNIX或Windows?你能發佈客戶端的代碼片段嗎? – Richie 2010-01-14 19:21:36

+1

答案在代碼中是正確的...看看BaseHTTPServer.py和SocketServer.py – ChristopheD 2010-01-14 19:49:07

+0

感謝您的指點。我很想知道答案,而不是在哪裏找到答案。 – 2010-01-14 23:10:45

回答

7

好吧,我閱讀代碼(我的Mac上,SocketServer.py是/System/Library/Frameworks/Python.framework/Versions/2.5/ LIB /的python2.5 /)。

的確,TCPServer正在關閉連接。在BaseServer.handle_request中,調用process_request,調用close_request。在TCPServer類中,close_request調用self.request.close(),而self.request只是用於處理請求的套接字。

所以我的問題的答案是「是」。

0

您確定客戶端沒有掛在服務器上?這有點太模糊,不能真正說出發生了什麼,但通常情況下,接受來自客戶端數據的服務器將退出讀取連接,不返回任何數據。

6

根據文檔,除非被提示,否則TCPServer和BaseRequestHandler都不會關閉套接字。 handle()finish()的默認實現什麼也不做。

幾件事情可能會發生:

  • 您關閉套接字本身或包裝它的請求,或致電server_close地方。
  • 套接字超時可能已經命中,並且您已經實現了一個關閉套接字的超時處理程序。
  • 客戶端可能實際上關閉了套接字。代碼真的有助於解決這個問題。

但是,我的測試證實了你的結果。一旦從服務器上的handle返回,無論是通過telnet或Python的socket模塊進行連接,您的連接顯示爲由遠程主機關閉。在內側把手循環處理套接字活動似乎工作:

def handle(self): 
    while 1: 
     try: 
      data = self.request.recv(1024) 
      print self.client_address, "sent", data 
     except: 
      pass 

一個簡短的谷歌代碼搜索證實,這是處理請求的典型方式:1234。老實說,有很多其他網絡庫可用於Python,如果我面臨抽象SocketServer提供和我的期望之間的斷開,我可能會看到。

我用來測試

代碼示例:

from SocketServer import BaseRequestHandler, TCPServer 

class TestRequestHandler(BaseRequestHandler): 
    def handle(self): 
     data = self.request.recv(1024) 
     print self.client_address, "sent", data 
     self.request.send(data) 

class TestServer(TCPServer): 
    def __init__(self, server_address, handler_class=TestRequestHandler): 
     TCPServer.__init__(self, server_address, handler_class) 

if __name__ == "__main__": 
    import socket 

    address = ('localhost', 7734) 
    server = TestServer(address) 
    server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
5
  1. 的tcpserver非常接近 '句柄' 後,每次連接
  2. ,同時對關閉

    def handle(self): 
        while 1: 
        try: 
         data = self.request.recv(1024) 
         print self.client_address, "sent", data 
        except: 
         pass 
    

    後續的代碼不能正常工作,這可能會更好:

    def handle(self): 
        while(1): 
         try: 
          self.data = self.request.recv(1024) 
          if not self.data: 
           print "%s close" % self.client_address[0] 
           break 
          print "%s wrote:" % self.client_address[0], self.data 
         except: 
          print "except" 
          break 
    
    1. reuseaddr不起作用,因爲綁定後太遲
    server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)