python/zmq/monitor

该博客介绍了如何使用PyZMQ库创建一个MonitoredQueue设备来监控客户端与服务器之间的通信。服务器运行在端口5555,MonitoredQueue作为中介监听4444端口,连接到5555,并在7777端口发布消息。客户端连接到4444端口进行通信。监控客户端通过7777端口接收和打印嗅探信息。MonitoredQueue允许在不影响通信的情况下进行消息嗅探,适用于系统监控和调试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

此解决方案基于MonitoredQueue example from pyzmq doc

服务器绑定到端口5555

服务器将绑定到端口5555。与其他示例不同,我将保持服务器作为固定部分,而不会更改它连接到monitoredqueue。但是,这种交换不是问题,也不会产生任何问题(只要您正确地调整MonitoredQueue)。在

MonitoredQueue绑定到端口4444,连接到端口5555,在端口7777上发布流量

MonitoredQueue位于客户端和服务器之间。它监听端口4444,向服务器发送请求,并将响应发送回客户端。同时,任何经过的消息都将在PUB socket上以相应的前缀“in”或“out”发布。稍后我们将看到,这些不仅包含前缀和请求/响应,还包含客户端的标识。在

客户端连接到端口4444

客户机可以直接连接到5555端口上的服务器,但这不允许我们嗅探通信量。出于这个原因,我们将客户机连接到端口4444,在这里MonitoredQueue正在等待服务器和嗅探。在

您将看到,客户机和服务器不必更改一行代码即可参与此交换。在

实码

server.py

在我们的例子中,服务器需要一个可以转换为整数的字符串,并返回一个值加倍的字符串。在

import zmq

def double_server(server_url="tcp://*:5555"):
    context = zmq.Context()
    socket = context.socket(zmq.REP)
    socket.bind(server_url)
    print "server started..."
    while True:
        req = socket.recv()
        print "server received request", req
        result = str(2*int(req))
        socket.send(result)
        print "server replied with", result

if __name__ == "__main__":
    double_server()

client.py

我们的客户机将尝试5次请求本地主机上端口4444的一些结果。在

^{pr2}$

您现在可以尝试直接连接到端口5555以查看它是否正常工作,但是对于我们的嗅探,它必须与MonitoredQueue通信。在

monitor.py

所有的魔法都来了。pyzmq已经提供了设备MonitoredQueue,所以我们可以简单地使用它。在

import zmq
from zmq.devices.monitoredqueuedevice import MonitoredQueue
from zmq.utils.strtypes import asbytes

def monitoredqueue(frontend_url="tcp://*:4444", server_url="tcp://localhost:5555", capture_url="tcp://*:7777"):
    mondev = MonitoredQueue(zmq.ROUTER, zmq.DEALER, zmq.PUB, asbytes("in"), asbytes("out"))
    mondev.bind_in(frontend_url)
    mondev.connect_out(server_url)
    mondev.bind_mon(capture_url)
    mondev.setsockopt_in(zmq.HWM, 1)
    mondev.start()
    print "monitored queue started"

if __name__ == "__main__":
    monitoredqueue()

有关套接字类型和别名的注意事项:

  • 在zmq路由器以前叫zmq.XREP公司在
  • 在zmq经销商以前叫zmq.XREQ公司在
  • 这些别名仍然有效。在

MonitoredQueue将发布在上传递的每个消息zmq.PUB公司端口7777上的插座。这些消息将以“in”和“out”作为前缀,还将包含一个带有标识字符串的帧。此标识字符串由路由器套接字分配,在交换期间,它对所有连接的客户端都是唯一的。此标识是所谓信封的一部分,来自由空框架分隔的请求/应答消息(稍后将看到)。在

monitorclient.py

这个监控客户端只是为了展示如何获取嗅探信息。在

它订阅端口7777,由监视器(MonitoredQueue)提供服务并将其打印出来。使用多部分消息是很重要的,否则我们会丢失一些信息。在

import zmq

def monitorclient(server_url="tcp://localhost:7777"):
    context = zmq.Context()
    socket = context.socket(zmq.SUB)
    socket.connect(server_url)
    socket.setsockopt(zmq.SUBSCRIBE, "")
    print "started monitoring client"

    while True:
        res = socket.recv_multipart()
        print res

if __name__ == "__main__":
    monitorclient()

快跑

我们需要打开4个控制台,在每个控制台中我们将启动一个python脚本

首先启动服务器:

$ python server.py

启动MonitoredQueue

$ python monitor.py

启动客户端,读取嗅探消息

$ python monitorclient.py

最后,启动客户机,尝试从MonitoredQueue代理的服务器获取一些响应

$ python client.py
request 0
0 result:  0
request 1
1 result:  2
request 2
2 result:  4
request 3
3 result:  6
request 4
4 result:  8

结果如预期。在

现在检查一下服务器.py输出:

$ python server.py
server received request 0
server replied with 0
server received request 1
server replied with 2
server received request 2
server replied with 4
server received request 3
server replied with 6
server received request 4
server replied with 8

毫不奇怪,一切顺利。在

我们的monitor.py不打印任何内容,我们将必须检查输出frommonitorclient.py

$ python monitorclient.py 
started monitoring client
['in', '\x00\xc4\x84\x1c\xf2\xc2.@\xd3\x86cN\x0e\x06\x7f\xaf\x0b', '', '0']
['out', '\x00\xc4\x84\x1c\xf2\xc2.@\xd3\x86cN\x0e\x06\x7f\xaf\x0b', '', '0']
['in', '\x00\xc4\x84\x1c\xf2\xc2.@\xd3\x86cN\x0e\x06\x7f\xaf\x0b', '', '1']
['out', '\x00\xc4\x84\x1c\xf2\xc2.@\xd3\x86cN\x0e\x06\x7f\xaf\x0b', '', '2']
['in', '\x00\xc4\x84\x1c\xf2\xc2.@\xd3\x86cN\x0e\x06\x7f\xaf\x0b', '', '2']
['out', '\x00\xc4\x84\x1c\xf2\xc2.@\xd3\x86cN\x0e\x06\x7f\xaf\x0b', '', '4']
['in', '\x00\xc4\x84\x1c\xf2\xc2.@\xd3\x86cN\x0e\x06\x7f\xaf\x0b', '', '3']
['out', '\x00\xc4\x84\x1c\xf2\xc2.@\xd3\x86cN\x0e\x06\x7f\xaf\x0b', '', '6']
['in', '\x00\xc4\x84\x1c\xf2\xc2.@\xd3\x86cN\x0e\x06\x7f\xaf\x0b', '', '4']
['out', '\x00\xc4\x84\x1c\xf2\xc2.@\xd3\x86cN\x0e\x06\x7f\xaf\x0b', '', '8']

在这里,您可以看到所有10条消息、5条请求、5条响应的打印输出。在

每个都有一个结构[prefix, identity, emptyframe, message],其中

  • prefix是“in”或“out”
  • identity是由MonitoredQueues分配给特定客户机的字符串。每次客户端连接时,此标识可能会更改。作为奖励,我们可以连接多个客户机,并且仍然有机会区分不同的客户机。如果您需要特定的客户机标识,请参阅client.py中带有{}的注释行。如果取消注释,您将看到"client_id_abc"作为客户的标识。在
  • emptyframe被视为'',它正在从消息数据中分隔信封。在
  • message是客户端询问的内容或服务器的答复。在

结论

  • 嗅探工作正常,PyZMQ已经为此提供了设备监视队列
  • 使用zmq.PUB嗅探不会阻止任何通信,您可以简单地忽略嗅探的数据,所有这些都可以工作。在
  • 对于生产,将MonitoredQueue设置为系统的固定部分,从而绑定到已知的IP地址和端口,这将是实际可行的。这需要对服务器进行更改,服务器必须连接(而不是当前绑定)。这样的更改是微不足道的,不会影响其余的代码和行为。如果只监视一个端点,还可以将监视器嵌入服务器(这需要两个线程,一个用于服务器,另一个用于监视器)。在
  • zmq对于这类任务来说是个很好的“乐高”。在
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值