2011-05-16 15 views
53

Este código funciona muy bien:¿Por qué zeromq no funciona en localhost?

import zmq, json, time 

def main(): 
    context = zmq.Context() 
    subscriber = context.socket(zmq.SUB) 
    subscriber.bind("ipc://test") 
    subscriber.setsockopt(zmq.SUBSCRIBE, '') 
    while True: 
     print subscriber.recv() 

def main(): 
    context = zmq.Context() 
    publisher = context.socket(zmq.PUB) 
    publisher.connect("ipc://test") 
    while True: 
     publisher.send("hello world") 
     time.sleep(1) 

Pero este código no se * trabajo:

import zmq, json, time 

def recv(): 
    context = zmq.Context() 
    subscriber = context.socket(zmq.SUB) 
    subscriber.bind("tcp://localhost:5555") 
    subscriber.setsockopt(zmq.SUBSCRIBE, '') 
    while True: 
     print subscriber.recv() 

def send(): 
    context = zmq.Context() 
    publisher = context.socket(zmq.PUB) 
    publisher.connect("tcp://localhost:5555") 
    while True: 
     publisher.send("hello world") 
     time.sleep(1) 

que plantea este error:

ZMQError: No such device

Por qué, no puede zeromq usar interfaces de host local?

¿Funciona solo en IPC en la misma máquina?

Respuesta

33

El problema está en línea:

subscriber.bind("tcp://localhost:5555") 

tratar de cambiar a:

subscriber.bind("tcp://127.0.0.1:5555") 
+0

me gusta usar una dirección más alta como 127.0.0.101 y variarla por aplicación. Más limpio que los enchufes IPC. –

+17

@fdb Sí, eso soluciona el problema, ¡pero no explica por qué! Necesita [más explicación] (http://stackoverflow.com/a/8958414/462302). – aculich

126

Como @fdb señala:

El problema está en línea:

subscriber.bind("tcp://localhost:5555") 

intente cambiar a:

subscriber.bind("tcp://127.0.0.1:5555") 

Sin embargo, esto merece más explicaciones para entender por qué.

La documentación para zmq_bind explica (énfasis en negrita):

The endpoint argument is a string consisting of two parts as follows: transport://address . The transport part specifies the underlying transport protocol to use. The meaning of the address part is specific to the underlying transport protocol selected.

Debido a que su ejemplo se utiliza TCP como protocolo de transporte nos fijamos en la documentación zmq_tcp para descubrir (una vez más, el énfasis es mío negrita):

When assigning a local address to a socket using zmq_bind() with the tcp transport, the endpoint shall be interpreted as an interface followed by a colon and the TCP port number to use.

An interface may be specified by either of the following:

  • The wild-card *, meaning all available interfaces.
  • The primary IPv4 address assigned to the interface, in its numeric representation.
  • The interface name as defined by the operating system.

Por lo tanto, si no está utilizando el comodín o el nombre de la interfaz, significa que debe usar una dirección IPv4 en forma numérica (no un nombre DNS).

Nota, esto solo se aplica al uso de zmq_bind! Por otro lado, es perfectamente posible utilizar un nombre DNS con zmq_connect como se discute más adelante en la documentación de zmq_tcp:

When connecting a socket to a peer address using zmq_connect() with the tcp transport, the endpoint shall be interpreted as a peer address followed by a colon and the TCP port number to use.

A peer address may be specified by either of the following:

  • The DNS name of the peer.
  • The IPv4 address of the peer, in its numeric representation.
+3

Esa es una implementación extraña. – huggie

+0

Ah una API no ortogonal – RichardOD

Cuestiones relacionadas