【问题标题】:Send NULL message in PyZMQ在 PyZMQ 中发送 NULL 消息
【发布时间】:2013-11-26 15:48:05
【问题描述】:

我正在尝试将以下示例 HTTP 服务器基于用 C 编写的 0MQ 转换为 Python:Hintjens' blog

def test_http_socket():
    ctx = zmq.Context()
    sock = ctx.socket(zmq.ROUTER)
    sock.setsockopt(zmq.ROUTER_RAW, 1)
    sock.bind("tcp://*:8080")
    while True:
        id_bytes = sock.recv()
        print("id=",id_bytes)
        request = sock.recv()
        print("request=",request)
        if b'/close' in request:
            return
        sock.send(id_bytes, zmq.SNDMORE)
        sock.send(b"""HTTP/1.0 200 OK
Content-Type: text/plain

Hello, world !""")
        sock.send(zmq.NULL)

问题出在下一行,我尝试翻译 C 表达式

zmq_send (router, NULL, 0, 0);

在 Python 中,我有以下堆栈跟踪:

Traceback (most recent call last):
  File "<pyshell#96>", line 1, in <module>
    test_http_socket()
  File "<pyshell#95>", line 18, in test_http_socket
    sock.send(zmq.NULL)
  File "socket.pyx", line 565, in zmq.backend.cython.socket.Socket.send     (zmq\backend\cython\socket.c:5104)
  File "socket.pyx", line 612, in zmq.backend.cython.socket.Socket.send (zmq\backend\cython\socket.c:4868)
  File "socket.pyx", line 168, in zmq.backend.cython.socket._send_copy (zmq\backend\cython\socket.c:1914)
  File "buffers.pxd", line 200, in buffers.asbuffer_r (zmq\backend\cython\socket.c:6833)
  File "buffers.pxd", line 151, in buffers.asbuffer (zmq\backend\cython\socket.c:6270)
TypeError: 0 does not provide a buffer interface.

实际上,sock.send 只能用于发送缓冲区或消息。 有没有办法从 Python 中以另一种方式使用 0MQ 的 zmq_send 来发送 NULL 帧?

顺便说一句,Github entry 中的注释表明即使在 C 中它也可能不会关闭与客户端的连接。 如何要求远程客户端关闭其连接(在 Python 中)?

我在 Windows 32 位上使用 libzmq 4.0.1 和 PyZMQ 14.0.1 而不是 Python 3.3.2。

【问题讨论】:

    标签: python zeromq pyzmq


    【解决方案1】:

    第一点:zmq.NULLZMQ_NULL 常量,用于 zeromq 的安全机制。例如:

    socket.mechanism = zmq.NULL # or zmq.PLAIN or zmq.CURVE
    

    它不是 NULL 特殊的 C 常量。

    要发送空消息,只需发送一个空字节串:

    socket.send(b'')
    

    第二点是您需要将空帧作为单独的消息发送,您没有这样做。 这是一个工作示例:

    def http_hello_world():
        ctx = zmq.Context()
        sock = ctx.socket(zmq.ROUTER)
        sock.router_raw = True
        sock.bind("tcp://*:8080")
        while True:
            id_bytes, request = sock.recv_multipart()
            print("id: %r" % id_bytes)
            print("request:", request.decode('utf8'))
            if b'/close' in request:
                return
    
            # send the body of the response
            sock.send_multipart([
                id_bytes,
    b"""HTTP/1.0 200 OK
    Content-Type: text/plain
    
    Hello, world!
    """
            ])
            # send an empty message to finish the response
            sock.send_multipart([
                id_bytes,
                b''
            ])
    

    顺便说一句,Github 条目中的一条注释表明,即使在 C 中,它也可能不会关闭与客户端的连接。如何要求远程客户端关闭其连接(在 Python 中)?

    我认为,只要你发送空帧终止消息,连接就应该关闭。

    【讨论】:

    • 今天早上我想到了,尝试在重新发送空帧之前发送 id_bytes。为了以防万一,我回到了 Stackoverflow,你提供的正是我的想法。而且效果很好!谢谢你。并感谢您对 zmq.NULL 的解释。
    猜你喜欢
    • 2016-03-18
    • 1970-01-01
    • 2015-08-20
    • 2016-08-20
    • 2016-09-23
    • 2019-07-23
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多