2016-06-08 97 views
1

下面是我創造我在程序的線程的基本概念:添加time.sleep到多線程程序解決了的UnicodeDecodeError在python

Main thread 
     | 
    ListenerCreator(The WebSocketServer thread) ---> Several listener threads(using log()) 

所以主線程創建一個線程ListenerCreator,連接到多個客戶端併爲每個客戶端創建一個偵聽器線程。下面簡要介紹一下監聽線程的功能: EDIT1: 我使用WebSockets從我的客戶端讀取/寫入數據。爲此我創建了自己的服務器。有一個標準規定的framing protocol - 我正在使用它。在客戶端,我簡單地使用WebSocket.send()並根據協議中給出的指令「解除掩碼」(參見上面鏈接中的第5.3節)。 如果有人請求它,我願意提供服務器代碼,但是,這裏有一個簡要介紹:

class WebSocketServer: 
    def start(): 
      #Open server socket, bind to host:port 
      while True: 
       #Accept client socket, start a new listener thread for self.log(client) 
    def log(client): 
      #Receive data using socket.socket.recv(1024) 
      #Unmask data as per the protocol 
      #Decode using data.decode("utf-8") 
      #Append to data_q while holding data_q_lock 

還有其他的方法 - 那些便於發,關閉,握手等。

同時在主線程:

while breaking!=len(client_list): 
     #time.sleep(0.5)  
     with data_q_lock: 
      for i in range(len(data_q)): 
       mes = data_q.pop() 
       for m in client_list: 
        if "#DONE"== mes: 
         breaking += 1 
       if(mes[:len("#COUNT:")] == "#COUNT:"): 
        print(mes) 

所以基本上這個循環中所做的是:環通的data_q,如果消息與「#COUNT」開始,打印郵件,並獲得一定數量後「#DONE」消息,退出循環。 如果time.sleep未註釋,則此代碼有效,但無time.sleep,我在日誌函數中收到UnicodeDecodeError。 此外,我只得到錯誤有時,有時程序完美。 (順便說一句,客戶端每次都發送相同的數據) 所以,我的問題是,爲什麼需要time.sleep? 我認爲這是與python中的GIL有關,因爲time.sleep釋放GIL。但是,即使在閱讀後我仍無法解決問題

+0

請說明如何從監聽器中的套接字讀取數據,它與您的問題非常相關:-) – donkopotamus

回答

0

當前沒有關於偵聽器如何從套接字讀取數據的信息。然而,這可能是由於套接字通常的誤解造成的。

向套接字發送的數據不是由套接字以任何方式「成幀」。試想一下,如果我發送消息「hello」三次下來一個套接字。然後,就像沒有換行寫入文件,下面將流動在插座上:

hellohellohello 

現在考慮讀者...讀取數據時,它如何知道一個消息(「你好」)開始和下一個?它不能,除非發送者和接收者同意如何將這些數據「框起來」。這可以通過同意以下某些協議來完成:

  • null-termination data;或
  • 固定大小的消息;或
  • 大小前綴消息。

問題就變得更復雜,當然,即使一旦你決定了數據應該如何被陷害,你不能保證socket.recv將返回一個「整體」的消息......它只會返回一個數據都被在當時的緩衝區中。它可能是一條消息,或一條消息和一半。它的工作是整理從套接字讀取的數據並將其分成消息。

談談你的問題,你在哪裏發送utf-8數據。讀者如何知道它已經閱讀完整的utf-8數據信息?最有可能的是,這裏發生的事情是,你只收到部分消息 ......還有更多的消息到達。

特別是,有效的utf-8字符可能包含多個字節。所以如果你的部分消息在一個字符的多字節utf-8表示的中間結束,那麼你肯定不能解碼它。

+0

謝謝!我添加了更多關於我實際使用套接字的信息。按照WebSocket協議使用大小前綴的消息。 – user6397000

+0

你得到一個'UnicodeDecodeError'幾乎可以肯定地表明你的數據有效載荷是不完整的......嘗試捕獲這個錯誤並檢查實際的幀以確保它是你的想法。 (我假設你意識到'socket.recv(1024)'可能會返回少於1024個字節?) – donkopotamus