2011-03-09 43 views
0

我正在運行一個從隊列中抓取消息,將其發送給客戶端並接收確認的線程。如果客戶端斷開連接,線程將捕獲套接字錯誤並終止。問題是如果msgQ爲空,則線程從不檢查套接字連接。有沒有辦法設置這個代碼,即使隊列是空的,套接字被檢查? (問題是,沒有消息,沒有什麼可以發送)Python:Queue.get()阻止檢查套接字連接的代碼

我需要發送一個特殊的乒乓球! msgQ爲空的消息(並檢查客戶端消息是日誌數據還是ping?)?任何幫助,將不勝感激。

def run(self): 
    while not self._terminate: 
     try: 
      msgs = self.msgQ.get() 

      self.sock.send(pickle.dumps(msgs)) 
      rdy = pickle.loads(self.sock.recv(2097152)) 
     except socket.error, EOFError: 
      print 'log socketmanager closing' 
      self.terminate() 
      break 
     except Empty: pass 
+0

self.sock.recv()是一個阻塞調用,除非你有非阻塞套接字。這意味着如果隊列中沒有消息,那麼發出一個self.sock.recv()將會阻塞並且不會繼續處理,直到收到某個消息。那是你想要做的嗎? – 2011-03-10 00:20:43

回答

1

如果msgQ爲空,則呼叫self.msgQ.get()會引發Empty例外,並完全跳過對self.sock.send()self.sock.recv()的呼叫。您的異常處理程序的Empty異常什麼也不做,所以您的代碼將busy wait,直到msgQ中出現的東西,而沒有調用sendrecv

一個可能的解決方案是使用python select module來檢查異常處理程序中的套接字。沿着這些線:

def run(self): 
    while not self._terminate: 
     try: 
      msgs = self.msgQ.get() 

      self.sock.send(pickle.dumps(msgs)) 
      rdy = pickle.loads(self.sock.recv(2097152)) 
     except socket.error, EOFError: 
      print 'log socketmanager closing' 
      self.terminate() 
      break 
     except Empty: 
      results = select.select([], [], [self.sock], 0.5) # timeout of 0.5 seconds 
      if self.sock in results[2]: 
       print 'exceptional condition on socket' 
       self.terminate() 
       break 
+0

這段代碼究竟做了什麼?我目前的解決方法是發送一個特殊的「ping?」 Queue.Empty情況下的套接字消息(並針對「ping?」與真實數據進行適當的客戶端處理)。 – 2011-03-10 18:54:23

+0

對'select.select'的調用會檢查套接字上的異常情況。特殊條件的確切定義取決於您的系統 - 請查閱python文檔以獲取更多信息。重點是查找套接字上發生的事件,而不需要調用'recv',因爲可能沒有任何數據可以接收。 'select'函數返回與三個參數列表相對應的3個列表的元組。如果參數列表中的套接字出現在結果列表中,那麼該套接字上發生了一些事情。 – srgerg 2011-03-10 20:49:33

+0

感謝您的信息,您贏了。 – 2011-03-11 19:12:50

0

如果您使用Queue.Queue你可以叫Queue.get()可選blocktimeout ARGS,或致電Queue.get_nowait()這相當於Queue.get(block=False),並會立即返回,如果隊列爲空:

try: 
    # wait for 1/10 second then return 
    msgs = self.msgQ.get(timeout=0.1) 
except Queue.Empty, qe: 
    # handle empty queue