2011-10-19 28 views
1

我想爲我的命令行服務器創建一個gui客戶端。但是,我遇到了一些惱人的問題,我似乎無法解決。Python插座Recv不能正常工作可能有人解釋

我不是100%確定實際問題是什麼,因爲有時代碼會起作用,其他時候它不會。我認爲主要的問題是,原來我試過

while 1: 
    self.data = s.recv(1024) 
    if not self.data(): 
      break 
    else: 
      print self.data() 

然後我就被髮送給它這個

for f in files: 
     s.send(f) 

每個f爲文件名的字符串。我預計它會在recv方面出現,因爲每個recv通話都會收到一個文件名,但是在一個recv通話中,我得到了一大塊文件名,我假設它的值爲1024個字符

這使得無法檢查結尾的數據,因此循環永遠不會退出。

這是代碼我現在

def get_data(self,size = 1024): 

    self.alldata = "" 
    while 1: 

     while gtk.events_pending(): 
      gtk.main_iteration() 

     self.recvdata = self.s.recv(size) 
     self.alldata += self.recvdata 
     if self.alldata.find("\r\n\r\nEOF"): 
      print "recieved end message" 
      self.rdata = self.alldata[:self.alldata.find("\r\n\r\nEOF")] 
      break 



    print "All data Recieved: " + str(len(self.rdata)) + "Bytes" 
    print "All data :\n" + self.rdata + "\n-------------------------------------------------" 

    self.infiles = self.rdata.split("-EOS-") 
    for nf in self.infiles: 
     if len(nf) > 2: 
      self.add_message(self.incomingIcon,nf) 

已在IM分鐘試圖讓客戶端從服務器讀取正確。我想要發生的是當命令列表輸入併發送到客戶端時,服務器發送回數據並將每個文件附加到列表存儲

有時這可以正常工作,其他時間只有1200個文件中的一個得到返回,如果它執行正常,如果我嘗試輸入另一個命令併發送它,整個gtk窗口就會出現並且程序變得無法響應。

對不起,我不能更好地解釋這個問題,我嘗試了很多不同的解決方案,所有這些解決方案給出了不同的錯誤。

,如果有人可以解釋的recv命令,以及爲什麼它可以起到錯誤這是即時通訊將數據發送到客戶端

if(commands[0] == 'list'): 
    whatpacketshouldlooklike="" 
    print "[Request] List files ", address 
    fil = list_files(path) 
    for f in fil: 
     sdata = f 
     whatpacketshouldlooklike += sdata + "-EOS-" 
     newSock.send(sdata +"-EOS-") 
     #print "sent: " + sdata 
     newSock.send("\r\n\r\nEOF") 
    whatpacketshouldlooklike += "\r\n\r\nEOF" 
    print "---------------------------------" 
    print whatpacketshouldlooklike 
    print "---------------------------------" 
+0

您的原帖是否有錯字? 'self.data = s.recv(1024)'會讓下一行'self.data()'看起來不太好。套接字上的'recv'方法不返回可調用對象afaik。 –

+2

stonemetal的回答是正確的。如果你對一個套接字進行了兩次send()調用,每個套接字都有一個20字節的字符串(例如一個文件名),那麼'recv()'結束可能在一個'recv()'中得到40個字節,可能在一個'recv()'和另一個字節上得到39個字節,或者它可能必須被調用40次,每次傳遞一個字節。所有你保證的是,它將盡最大努力提供最終產品,並且不會出現任何故障。 –

回答

3

您在第一部分出現了問題怎麼就是插座不是基於流基於消息。您需要提供一個消息抽象層來放在流的頂部。這樣管道的另一端就知道發生了什麼(作爲一個命令的一部分需要多少數據),而不是猜測應該發生什麼。

+0

你好,我明白你的意思,我認爲這將是一個有趣的測試,試圖寫我自己的協議。虐待嘗試和實施的結構模塊建議由ms4py – user1003967

2

使用抽象層(Pyro,XML-RPC,zeromq)或定義自己的協議來區分消息。

例如,作爲自己的協議,您可以在每個字符串之前將消息的長度作爲「標題」發送。在這種情況下,您應該使用struct模塊將長度解析爲二進制格式。再問一次,如果你想這樣做,但我強烈建議選擇一個提到的抽象層。

2

您的代碼存在不同的問題。

讓我們從一些人已經評論過的基礎開始,在send()和recv()之間沒有關係,你不能控制recv(call)返回哪部分數據,你需要某種在你的情況下,它可能就像使用「\ n」終止命令字符串一樣簡單,並檢查服務器上的「\ n」以使用數據。

現在其他問題:

  • 您正在使用發送而不檢查它的回報大小,發送()不能保證數據完全寫入,如果你需要,請使用sendall()。
  • 通過在阻塞套接字(默認)中使用recv(1024),您的服務器代碼可能會等待接收1024字節,這將不允許您在獲取完整塊之前處理消息,您需要使用非阻塞套接字和選擇模塊。