2012-12-31 120 views
1

我有幾個測試客戶端每次都遇到相同的問題。客戶端可以連接,並且可以發送他們的第一條消息,但是之後服務器停止響應該客戶端。我懷疑問題與s.accept()有關,但我不確定究竟是什麼錯誤或如何解決它。Python服務器故障

def startServer(): 
    host = '' 
    port = 13572 
    backlog = 5 
    size = 1024 

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    s.bind((host,port)) 
    s.listen(backlog) 

    print "Close the command prompt to stop Gamelink" 

    while 1: 
     try: 
      client, address = s.accept() 
      data = client.recv(size) 
      if data: 
       processData(data) 
       client.send("OK") 
      else: 
       print "Disconnecting from client at client's request" 
       client.close() 
     except socket.error, (value, message): 
      if s: 
       print "Disconnecting from client, socket issue" 
       s.close() 
      print "Error opening socket: " + message 
      break 
     except: 
      print "Gamelink encountered a problem" 
      break 
     print "End of loop" 
    client.close() 
    s.close() 

服務器旨在通過本地網絡訪問,並且它需要重量輕,非常迅速作出反應,因此,如果另一個實現(如基於線程)將是滿足這些要求的更好,請讓我知道。預期的應用是用作遠程遊戲鍵盤,因此需要低資源使用和高速度。

+1

你應該把'accept'放在循環之外。此外,該服務器將只接受一個連接。如果你想要一個服務於多個客戶端的真實服務器,你需要多路複用連接,比如使用'select'或'poll'。 – Keith

+0

一個連接實際上對我所要做的事情來說是完美的,它看起來像解決了我的問題。謝謝! –

回答

0

直接使用socket編寫服務器將會很困難。正如Keith所說,您需要以某種方式複用連接,例如selectpoll或線程或fork。你可能認爲你只需要一個連接,但是當有些事情打嗝並且連接丟失時你會怎麼做?如果服務器尚未意識到連接丟失,您的服務器是否能夠響應來自客戶端的重新連接嘗試?

如果您的網絡需求是基本的,您可能可以讓其他人爲您處理所有的聆聽和接受問題。您不指定平臺,但此類程序的示例在Mac OS上爲launchd,在Linux上爲xinetd。這些工具的細節有所不同,但基本上可以在某些配置文件中配置它們以偵聽某個端口上的連接。當他們得到它時,他們負責建立連接,然後他們exec()您的程序與stdinstdout針對插座,因此您可以簡單地使用您可能已知的所有基本IO,如printsys.stdin.read()

像xinitd和launchd這樣的解決方案的問題在於,對於每個新連接,它們必須是fork()exec()程序的新實例。這些操作比較繁重,因此大量連接或高速連接可能會影響服務器的極限。但更糟糕的是,由於每個連接都在一個獨立的過程中,因此在它們之間共享數據非常困難此外,您可能發現在進程之間進行通信的大多數解決方案都涉及到blocking API,現在您又回到了與select或線程或類似內容複用的問題。

如果這樣不能滿足您的需求,我認爲您最好學習使用更高級別的網絡框架,以解決您在沿着socket的路徑時不可避免會遇到的所有問題。我建議的一個這樣的框架是Twisted。除了處理連接的平凡細節以及在它們之間複用IO的更復雜的任務之外,您還將擁有一個巨大的工具庫,這將使實現您的協議變得更容易。