在PyZMQ中发送NULL消息

时间:2013-11-26 15:48:05

标签: python zeromq pyzmq

我正在尝试将以下示例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。

1 个答案:

答案 0 :(得分:3)

第一点: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中)?

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