2012-12-31 38 views
2

我想學習如何使用套接字和有用的異步後端。我已經開始在python與asyncore。閱讀各種在線帖子後,我寫了一個非常簡單的聊天服務器和連接客戶端,下面轉載。非常簡單的python客戶端/服務器工作,但奇怪的延遲

它似乎工作。我打開一個Python交互式會話並鍵入

> import chatserver 
> server = chatserver.EchoServer('localhost', 7667) 
> server.serve() 

然後我打開另一個IPython的交互式會話和類型

> import chatserver 
> cxn = chatserver.Connection() 
> cxn._connect('localhost', 7667) 

當我這樣做,我得到的服務器窗口中的日誌輸出指示連接都有已經制成。好。然後,我鍵入

> cxn.say('hi') 

沒有任何反應了一會兒,然後日誌消息顯示服務器和客戶端的預期。

  1. 爲什麼這個延遲會發生?
  2. 我是否正確使用日誌功能?
  3. 我使用了線程來讓它可以使用交互式會話,而asyncore循環則可以使用交互式會話。我是否以合理的方式做到這一點?
  4. (可選)如果我在Connection._connect函數中沒有包含行self.out_buffer="",我會收到一個錯誤消息,提示.out_buffer不存在。這是怎麼回事?
import asyncore 
import socket 
import logging 
import threading 
logging.basicConfig(level=logging.DEBUG, format="%(created)-15s %(msecs)d %(levelname)8s %(thread)d %(name)s %(message)s") 
log = logging.getLogger(__name__) 

class Connection(asyncore.dispatcher_with_send): 
    def __init__(self): 
     asyncore.dispatcher.__init__(self) 

    def _connect(self, host, port, timeout=5, password=None): 
     self.host = host 
     self.port = port 
     self.out_buffer="" 
     self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.connect((host, port)) 
     #Run the asyncore loop in its own thread so that we can use the interactive session 
     self.loop = threading.Thread(target=asyncore.loop) 
     self.loop.daemon = True 
     self.loop.start() 

    def say(self, msg): 
     self.out_buffer = msg 

    def handle_read(self): 
     data = self.recv(4096) 
     log.debug('Received %s'%data) 

class EchoHandler(asyncore.dispatcher_with_send): 

    def handle_read(self): 
     log.debug("handle_read") 
     data = self.recv(1024) 
     log.debug("after recv") 
     if data: 
      log.debug("got data: %s"%data) 
      self.out_buffer = data 
     else: 
      log.debug("got null data") 

class EchoServer(asyncore.dispatcher): 
    SOCKET_TYPE = socket.SOCK_STREAM 
    ADDRESS_FAMILY = socket.AF_INET 
    def __init__(self, host, port): 
     self.address = (host,port) 
     asyncore.dispatcher.__init__(self) 
     self.create_socket(self.ADDRESS_FAMILY, self.SOCKET_TYPE) 
     log.debug("bind address=%s %s"%(host,port)) 
     self.bind(self.address) 
     self.listen(1) 

    def fileno(self): 
     return self.socket.fileno() 

    def serve(self): 
     asyncore.loop() 
     #Start asyncore loop in new thread 
#  self.loop = threading.Thread(target=asyncore.loop) 
#  self.loop.daemon = True 
#  self.loop.start() 

    def handle_accept(self): 
     """Deal with a newly accepted client""" 
     (connSock, clientAddress) = self.accept() 
     log.info("conn made: clientAddress=%s %s"%(clientAddress[0], clientAddress[1])) 
     #Make a handler for this connection 
     EchoHandler(connSock) 

    def handle_close(self): 
     self.close() 
+0

你不是發送和結束與您的文本的行,可以嗎? –

+0

試過了。沒有不同。 –

+0

可能是Nagle算法,Google套接字選項TCP_NODELAY。 – cdarke

回答

0

事實證明,問題是Eero建議的。

我做了兩個變化:

在EchoServer的

asyncore.loop()asyncore.loop(timeout=0.1)

在連接

self.loop = threading.Thread(target=asyncore.loop)self.loop = threading.Thread(target=asyncore.loop, kwargs={'timeout':0.1})

的響應是現在快得多。這看起來像是黑客,但如果有人能夠以適當的方式解釋獲得相同效果的方式,請參與。

1

望着你是依靠asyncore.dispatcher_with_send調用send()的asyncore文檔和asyncore.loop()默認的超時時間爲30秒。這可以解釋延遲。

+0

好吧,這絕對是有前途的,但爲什麼超時問題在這裏。我不能正確地觸發某件事。 –

相關問題