当套接字绑定到多个地址并不总是有效时,执行ZeroMQ轮询

时间:2018-11-13 21:57:45

标签: zeromq

我正在使用ZeroMQ作为基础结构来构建应用程序。我正在尝试调试管道,但遇到了意外情况。为了简单起见,示例在python中,但是我的目标是C ++

这是世界服务器,以轮询循环编写,并绑定到两个地址

#!/usr/bin/python

from __future__ import print_function

import zmq
context = zmq.Context()

s = context.socket(zmq.REP)
#s.bind("tcp://*:5555")
s.bind("ipc://world.ipc")

poller = zmq.Poller()
poller.register(s, zmq.POLLIN)

while True:
    socks = dict(poller.poll())
    print("... poll returned ...", socks)

    if socks.get(s) == zmq.POLLIN:
        m = s.recv()
        print("Received request: [{0}]".format(m))

        s.send(b"World")

这是您好客户端,使用地址之一

#! /usr/bin/python

from __future__ import print_function

import zmq

context = zmq.Context()

# Socket to talk to server
print("Connecting to hello world server...")
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:5555")
socket.connect("ipc://world.ipc")

# Do 10 requests, waiting each time for a response
for request in range(10):
    print("Sending request {0} ...".format(request))
    socket.send(b"Hello")

    # Get the reply
    message = socket.recv()
    print("Received reply {0} [ {1} ]".format(request, message))

如果hello客户端连接到两个地址,则一切正常。如果服务器(仅)绑定到IPC地址,并且客户端同时连接到IPC和TCP地址(按该顺序),则将仅收到一个响应,然后客户端将挂起。如果首先连接了TCP地址,则不会收到任何响应。

如果world服务器绑定到两个地址,则无论服务器绑定地址的顺序如何,客户端似乎都更健壮。

但是,由于嵌入在wsgiref Web服务器中的客户端(与我所需的实现更接近)略有不同,我的IPC地址始终出现故障:

#!/usr/bin/python
from __future__ import print_function

import zmq
context = zmq.Context()

import wsgiref
from wsgiref.simple_server import make_server

html_head = """<html><head>{meta}<title>{title}</title>{script}</head>"""

def create_head(title, meta="", script=""):
    return html_head.format(title=title, meta=meta, script=script)

def create_foot():
    return "</body></html>"

default_resp_headers = [
    ('Content-Type', 'text/html; charset=utf-8'),
    ]

import sys
class MyApp(object):
    def doIndex(self, environ):
        # Handle the default case

        response_body = [ create_head("Hello App"),
"""
<body>
<h1>Text goes here</h1>
<a href='/hello'>Hello World</a>
""",
                      create_foot(),
    ]

        status = '200 OK'
        response_headers = default_resp_headers[:]

        return status, response_headers, response_body

    def do_hello(self, environ):
        socket = context.socket(zmq.REQ)
        print("DEBUG: connecting to hello socket"); sys.stdout.flush()
        socket.connect("ipc://world.ipc")
#        socket.connect("tcp://localhost:5555")
        print("DEBUG: connected; sending hello"); sys.stdout.flush()
        socket.send(b"Hello")
        print("DEBUG: sent; receiving reply"); sys.stdout.flush()

        response_body = [ create_head("Remote Hello"),
        ]
        if socket.poll(2000) == zmq.POLLIN:
            message = socket.recv()
            print("DEBUG: received", message); sys.stdout.flush()

            response_body.append(
"""<body>
<h1>Hello {message}</h1>
""".format(message=message)
                )

            status = '200 OK'
        else:
            response_body.append(
"""<body><h1>Error</h1><p>Hello Server not responding</p> """
            )
            status = '504 Gateway Timeout'

        response_body.append(create_foot())
        response_headers = default_resp_headers[:]
        return status, response_headers, response_body

    def __call__(self, environ, start_response):
        wsgiref.util.shift_path_info(environ)
        path = environ.get('SCRIPT_NAME', '/')[1:]  # strip the leading /
        method_name = "do_"+path
        print("DEBUG: finding", method_name)
        if not hasattr(self, method_name): method_name = "doIndex"

        print("DEBUG: calling", method_name)
        method = getattr(self, method_name)
        print("DEBUG: method", repr(method))

        status, response_headers, response_body = method(environ)

        # the content-length is the sum of all string's lengths
        content_length = sum([len(s) for s in response_body])
        response_headers.append( ('Content-Length', str(content_length)) )

        start_response(status, response_headers)
        return response_body

def event_loop(interface, port):
    httpd = make_server(interface, port, MyApp())

    dispatch = {}
    poller = zmq.Poller()

    # For each socket to be watched, register with the poller and set a dispatch function. 
    poller.register(httpd, zmq.POLLIN)
    dispatch[httpd.fileno()] = httpd.handle_request  # note this is the bound function, not the invocation

    while True:
        for s,f in poller.poll():
            if f == zmq.POLLIN: dispatch[s]()

if __name__ == "__main__":
    event_loop("", 8051)

发生了很多事情,不一定与问题有关。关键部分是do_hello方法。发出curl http://localhost:8051/hello之类的请求时,将调用此方法。如果套接字连接到IPC地址,则请求超时。如果它连接到TCP地址,则始终可以使用。

我希望这很清楚。我仍在学习ZMQ,因此,如果我错过了明显的事情,欢迎反馈。

0 个答案:

没有答案