在Python中向客户端推送消息
我想实现一个系统,可以在需要的时候“推送”消息给客户端。简单来说,我需要的是从一个Python服务器向Python客户端“推送”文本。接收到的文本会被解析成客户端需要执行的操作(我已经知道如何处理这些操作,一旦收到“操作文本”)。
我可以每隔几秒检查一次是否有新的“操作文本”在等待,但我觉得这种方法不够可靠,也不适合成千上万的客户端。实时性在这里非常重要。
有没有什么建议呢?
2 个回答
7
你可以使用Redis的发布订阅模型,了解更多内容在这里。
Redis 是一个非常灵活且快速的工具。
举个例子:(来自 这个链接)
import redis
import unittest
class PubSubTestCase(unittest.TestCase):
def setUp(self):
self.connection_pool = redis.ConnectionPool()
self.client = redis.Redis(connection_pool=self.connection_pool)
self.pubsub = self.client.pubsub()
def tearDown(self):
self.connection_pool.disconnect()
def test_channel_subscribe(self):
self.assertEquals(
self.pubsub.subscribe('foo'),
['subscribe', 'foo', 1]
)
self.assertEquals(self.client.publish('foo', 'hello foo'), 1)
self.assertEquals(
self.pubsub.listen().next(),
{
'type': 'message',
'pattern': None,
'channel': 'foo',
'data': 'hello foo'
}
)
self.assertEquals(
self.pubsub.unsubscribe('foo'),
['unsubscribe', 'foo', 0]
)
def test_pattern_subscribe(self):
self.assertEquals(
self.pubsub.psubscribe('fo*'),
['psubscribe', 'fo*', 1]
)
self.assertEquals(self.client.publish('foo', 'hello foo'), 1)
self.assertEquals(
self.pubsub.listen().next(),
{
'type': 'pmessage',
'pattern': 'fo*',
'channel': 'foo',
'data': 'hello foo'
}
)
self.assertEquals(
self.pubsub.punsubscribe('fo*'),
['punsubscribe', 'fo*', 0]
)
2
我建议每个客户端都和服务器建立一个套接字连接。每个客户端可以运行一个线程,这个线程会在后台尝试从套接字中读取数据(也就是在等待数据到来时不会阻塞其他操作)。当服务器向这个套接字写入数据时,客户端应该能立刻收到。个人认为,客户端的连接应该继承自 telnetlib.telnet
,因为它提供了一个很方便的 read_until
方法。大概可以这样做:
class RPCConnection(object, Telnet):
def __init__(self, host = 'localhost', port = 9198, auto = True):
Telnet.__init__(self)
self.host, self.port, self.connected = host, port, False
if auto:
self._connect()
def _connect(self):
self.open(self.host, self.port)
self.connected = True
def _disconnect(self):
self.close()
self.connected = False
def _send(self, dict):
self.write(json.dumps(dict))
def _recv(self):
resp = self.read_until('\n')
try:
return json.loads(resp)
except Exception, e:
print e
print resp