等待gevent套接字和Redis阻塞blpop
我正在使用 gevent 的 StreamServer 来处理来自客户端的连接。
当客户端连接上后,它会向服务器发送一些消息,服务器会处理这些消息。这一切都运行得很好。但有时候,服务器也需要向特定的客户端发送消息。
我打算用 Redis 来实现这个功能。我创建了一个队列,用特定的客户端 ID 作为键。当客户端发送消息后,我会检查这个队列,如果有消息,我就把它发回给客户端。
这种方法的缺点是,服务器只能在客户端发送消息之后才能发送消息。
有没有办法让我同时等待接收数据和 Redis 的 blpop,这样我就可以在消息准备好后立即把它发回给客户端,而不是等到客户端发送下一条数据?
import gevent
from gevent import socket
from gevent.server import StreamServer
import redis
r = redis.Redis('localhost')
def handle_echo(sock, address):
fp = sock.makefile()
while True:
line = fp.readline()
if line:
client_id = line.split(",")[0]
if r.llen('%s:servercmds' % client_id) > 0:
tosend = r.lrange('%s:servercmds' % imei, 0, 0)[0]
try:
fp.write(tosend)
fp.flush()
r.lpop('%s:servercmds' % imei)
except:
print('cannot send data to client')
else:
break
sock.shutdown(socket.SHUT_WR)
sock.close()
server = StreamServer(('', 8045), handle_echo, spawn=10000)
server.serve_forever()
1 个回答
1
你需要让客户端保持连接,这样你才能把消息发回去,或者客户端自己也可以在监听消息。
补充说明:这段代码是我随便想出来的。在我看来,把读取和写入分开处理是很常见的做法。不过,这并不是你可以使用的唯一方式。
import gevent
from gevent import socket
from gevent.server import StreamServer
import redis
r = redis.Redis('localhost')
def handle_echo(sock, address):
def read_loop(sock):
while True:
try:
socket.wait_read(sock.fileno())
except socket.error:
break
# read from socket
def write_loop(sock):
while True:
try:
socket.wait_write(sock.fileno())
except socket.error:
break
# write to socket
jobs = [gevent.spawn(func, sock) for func in (read_loop, write_loop)]
gevent.joinall(jobs)
server = StreamServer(('', 8045), handle_echo)
server.serve_forever()