问题描述
据我所了解的客户端 - 服务器模型的基本知识,一般只有客户端可以发起请求;服务器响应它们。现在我遇到了一个系统,服务器通过相同的持久TCP连接发送异步消息回到客户端。所以,几个问题:
As far as I understand the basics of the client-server model, generally only client may initiate requests; server responds to them. Now I've run into a system where the server sends asynchronous messages back to the client via the same persistent TCP connection whenever it wants. So, a couple of questions:
- 这是一个正确的事吗?
- 我可以使用这些模式/方法在Python中为这样的系统实现一个客户端吗?更改服务器不是一个选项。
显然,客户端必须同时监视本地请求队列服务器),以及来自服务器的传入消息。每个连接启动两个线程(Rx和Tx)不适合我。在此处使用 select()
是一个主要的PITA。
Obviously, the client has to watch both the local request queue (i.e. requests to be sent to the server), and the incoming messages from the server. Launching two threads (Rx and Tx) per connection does not feel right to me. Using select()
is a major PITA here. Do I miss something?
推荐答案
在python中处理异步io时,我通常使用一个库,例如或。这些库的目标是允许以同步方式编写的应用程序通过后端反应器进行多路复用。
When dealing with asynchronous io in python I typically use a library such as gevent or eventlet. The objective of these libraries is allow for applications written in a synchronous to be multiplexed by a back-end reactor.
这个基本示例演示了启动两个绿线程/ co - 例程/纤程来处理TCP双工的任一侧。双工的发送端正在侦听异步队列。
This basic example demonstrates the launching of two green threads/co-routines/fibers to handle either side of the TCP duplex. The send side of the duplex is listening on an asynchronous queue.
这是在一个硬件线程中执行的。 Gevent&& eventlet在他们的文档中有更实质的例子,我在下面提供了。
This is all performed within a single hardware thread. Both gevent && eventlet have more substantive examples in their documentation that what I have provided below.
如果你运行 nc -l -p 8000
您将看到012打印出来。一旦netcat退出,此代码将被终止。
If you run nc -l -p 8000
you will see "012" printed out. As soon netcat is exited, this code will be terminated.
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
这篇关于是否可以通过同一TCP连接从服务器向客户端发送异步通知?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!