我正在尝试学习如何使用套接字和一个有用的异步后端。我用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')
暂时没有任何事情发生,然后按预期显示服务器和客户端的日志消息。
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 :(得分:1)
查看asyncore文档,您依靠asyncore.dispatcher_with_send
来调用send()
,asyncore.loop()
的默认超时为30秒。这可以解释延迟。
答案 1 :(得分: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})
现在响应速度更快。这看起来像是一个黑客,但如果有人可以解释一种方法以正确的方式获得相同的效果,请做出贡献。