就我所理解的客户端-服务器模型的基本知识而言,通常只有客户端可以启动请求;服务器会响应它们。现在,我遇到了一个系统,在这个系统中,服务器随时通过相同的持久TCP连接向客户端发送异步消息。所以,有几个问题:
显然,客户端必须同时监视本地请求队列(即发送到服务器的请求)和来自服务器的传入消息。每个连接启动两个线程(Rx和Tx)对我来说是不合适的。在这里,使用select()
是一个主要的问题。我错过了什么吗?
发布于 2013-12-25 19:22:49
在python中处理异步io时,我通常使用一个库,如盖特姆或盛事。这些库的目标是允许以同步方式编写的应用程序被后端反应堆复用。
这个基本示例演示了启动两个绿色线程/协同例程/光纤来处理TCP双工的任何一方。双工的发送端正在侦听异步队列。
这都是在一个硬件线程中执行的。gevent && eventlet在他们的文档中都有更多的实质性示例,我在下面已经提供了这些例子。
如果您运行nc -l -p 8000
,您将看到"012“打印出来。一旦netcat退出,此代码将被终止。
from eventlet import connect, sleep, GreenPool
from eventlet.queue import Queue
def handle_i(sock, queue):
while True:
data = sock.recv(8)
if data:
print(data)
else:
queue.put(None) #<- signal send side of duplex to exit
break
def handle_o(sock, queue):
while True:
data = queue.get()
if data:
sock.send(data)
else:
break
queue = Queue()
sock = connect(('127.0.0.1', 8000))
gpool = GreenPool()
gpool.spawn(handle_i, sock, queue)
gpool.spawn(handle_o, sock, queue)
for i in range(0, 3):
queue.put(str(i))
sleep(1)
gpool.waitall() #<- waits until nc exits
发布于 2013-12-25 09:02:24
我相信您正在努力实现的目标有点类似于jsonp
。发送到客户端时,通过您所知道的回调方法发送,该回调方法存在于客户端中。
就像你要发送"some data xyz"
,就像发送server.send("callback('some data xyz')");
一样。这个建议是针对javascript的,因为它执行返回的代码,就好像它是通过那个方法调用的一样。而且我相信您可以很困难地将这个理论移植到python。但我不确定。
发布于 2013-12-25 10:17:38
是的,这是非常正常的,而且服务器也可以在连接完成后向客户端发送消息,就像在telnet服务器启动连接时,它会向您发送一条用于功能交换的消息,然后它会询问您的用户名和密码。
您可以很好地使用select(),或者如果我在您的位置上,我会生成一个单独的线程来接收来自服务器的异步消息&这样主线程就可以自由地进行进一步的处理了。
https://stackoverflow.com/questions/20774949
复制