我正在使用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,因此,如果我错过了明显的事情,欢迎反馈。