Here are the "sender" and "receiver" I am using.
sender.py
import time
import zmq
context = zmq.Context()
sender = context.socket(zmq.PUSH)
sender.connect("tcp://127.0.0.1:5557")
c = 0
while True:
sender.send_json(c)
print "Sent {}".format(c)
c += 1
time.sleep(1)
reciever.py
import zmq
context = zmq.Context()
receiver = context.socket(zmq.PULL)
receiver.connect("tcp://127.0.0.1:5557")
while True:
m = receiver.recv_json()
print m
When I start the receiver then start the sender nothing is written to stdout on the receiver's cmd (I am trying to get this to work on windows 7). I've added inbound and outbound exceptions to the firewall for port 5557 and running netstat -an doesn't show anything running on port 5557. Lastly I am using zmq 2.2.0.
In your sender.py you should write sender.bind, not sender.connect.
Related
I would like to use XSUB/XPUB to enable multiple ZMQ publishers and subscribers. Everything works when I use zmq.proxy(xpub_socket, xsub_socket), but I need something custom because I need to write code between XSUB and XPUB that examines the messages.
Here's where I'm at:
import time
import zmq
context = zmq.Context()
address = '127.0.0.1'
pub_port = '3000'
sub_port = '3001'
# XSUB socket
xsub_socket = context.socket(zmq.XSUB)
xsub_socket.bind(f'tcp://{address}:{pub_port}')
# XPUB socket
xpub_socket = context.socket(zmq.XPUB)
xpub_socket.bind(f'tcp://{address}:{sub_port}')
time.sleep(1)
# PUB socket
pub_socket = context.socket(zmq.PUB)
pub_socket.connect(f'tcp://{address}:{pub_port}')
# SUB socket
sub_socket = context.socket(zmq.SUB)
sub_socket.subscribe('')
sub_socket.connect(f'tcp://{address}:{sub_port}')
time.sleep(1)
pub_socket.send_string('test')
time.sleep(1)
print(poller.poll(0))
The values sent from the PUB socket do not reach the XSUB socket.
I read here that the first byte needs to be 1. Both of these also don't work:
pub_socket.send(b'\x01')
pub_socket.send_multipart([b'\x01', 'test'.encode('utf-8')])
What am I doing wrong here?
A PUB socket won't send any messages to an XSUB socket unless it has received a subscription request, which you get by calling subscribe on a SUB socket.
The only way those subscription messages get passed through is if you set up your XSUB/XPUB proxy.
Here's a simple proxy that connects an XPUB and XSUB socket, printing out messages it receives in either direction:
import zmq
ctx = zmq.Context()
xpub_sock = ctx.socket(zmq.XPUB)
xpub_sock.bind("tcp://127.0.0.1:3000")
xsub_sock = ctx.socket(zmq.XSUB)
xsub_sock.bind("tcp://127.0.0.1:3001")
poller = zmq.Poller()
poller.register(xpub_sock, zmq.POLLIN)
poller.register(xsub_sock, zmq.POLLIN)
while True:
socks = dict(poller.poll())
if xpub_sock in socks and socks[xpub_sock] == zmq.POLLIN:
msg = xpub_sock.recv_multipart()
print("(sub)", msg)
xsub_sock.send_multipart(msg)
elif xsub_sock in socks and socks[xsub_sock] == zmq.POLLIN:
msg = xsub_sock.recv_multipart()
print("(pub)", msg)
xpub_sock.send_multipart(msg)
If I connect to this with an PUB socket, like this...
import zmq
import time
ctx = zmq.Context()
pub_sock = ctx.socket(zmq.PUB)
pub_sock.connect("tcp://localhost:3001")
while True:
pub_sock.send_string("test")
time.sleep(1)
...I won't see any messages arriving at the XSUB socket, because
there are no active subscriptions. However, if I connect a SUB
socket to the XPUB socket and set a subscription...
import zmq
ctx = zmq.Context()
sub_sock = ctx.socket(zmq.SUB)
sub_sock.connect("tcp://localhost:3000")
sub_sock.subscribe("")
while True:
msg = sub_sock.recv()
print(msg)
...then I will start to see messages passing from the PUB socket to
the XSUB socket, and then from the XPUB socket to the SUB
socket.
For a project I need to communicate between C++ and Python via ZMQ over the WLAN network.
If I use my C++ implementation, everything works fine. I just type in the IP+Port number at the client.bind("tcp:// ...) and I can send messages via WLAN.
If I try the same with the Python Code, it does not work.
So I just tested the python examples (so no C++ anymore): http://zguide.zeromq.org/py:durapub
http://zguide.zeromq.org/py:durasub
I replaced the >localhost< in the client with the IP of my host computer. I do not receive any messages. I am using exactly the code from the example, except the replacement.
Here is the Code:
PUBLISHER:
import zmq
import time
context = zmq.Context()
# Subscriber tells us when it's ready here
sync = context.socket(zmq.PULL)
sync.bind("tcp://*:5564")
# We send updates via this socket
publisher = context.socket(zmq.PUB)
publisher.bind("tcp://*:5565")
# Wait for synchronization request
sync_request = sync.recv()
# Now broadcast exactly 10 updates with pause
for n in xrange(10):
msg = "Update %d" % n
publisher.send(msg)
time.sleep(1)
publisher.send("END")
time.sleep(1) # Give 0MQ/2.0.x time to flush output
SUBSCRIBER
import zmq
import time
context = zmq.Context()
# Connect our subscriber socket
subscriber = context.socket(zmq.SUB)
subscriber.setsockopt(zmq.IDENTITY, "Hello")
subscriber.setsockopt(zmq.SUBSCRIBE, "")
subscriber.connect("tcp://192.168.2.119:5565")
# Syncronize with the publisher
sync = context.socket(zmq.PUSH)
sync.connect("tcp://192.168.2.119:5564")
sync.send("")
# Get updates, expect random Ctrl-C death
while True:
data = subscriber.recv()
print data
if data == "END":
break
Its exactly the example code, except that I changed localhost to the IP Adress of my publisher in the Subscriber-Code. Btw, I did the same in the C++ example Code and it works.
I am trying to publish a message(it's like broadcast when using raw sockets) to my subnet with a known port but at subscriber end, the message is not received. The idea is the IP address of the first machine should not be known to the second machine that's why I am using broadcast IP. With UDP or TCP raw socket, it works but I am trying to learn pub-sub pattern not sure how to incorporate that idea.
This is my codes:
Publisher:
import zmq
import sys
import time
context=zmq.Context()
socket=context.socket(zmq.PUB)
socket.bind("tcp://192.168.1.255:5677")
while True:
data='hello'.encode()
socket.send(data)
#time.sleep(1)
Subscriber:
context=zmq.Context()
sub=context.socket(zmq.PUB)
sub.setsocketopt(zmq.SUBSCRIBE, "".encode())
sub.connect('tcp://192.168.1.255:5677')
sub.recv()
print(sub.recv())
In terms of raw UDP, I wrote a code which works perfectly.
broadcast:
def broadcast(Host,port):
#send bd
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
msg=get_ip_data("wlp3s0")
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
time.sleep(1.5)
# print("yes sending", client)
sock.sendto(msg.encode(), (Host,port))
recv:
def broadcast_recv():
#listen bd
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind((get_bd_address("wlp1s0"),12345))
# receive broadcast
msg, client = sock.recvfrom(1024)
a=(msg.decode())
print(a)
It seems you forgot the zmq.SUB in the subscriber side. Also you used sub.setsocketopt() instead of sub.setsockopt().
Try it:
Publisher:
import zmq
import time
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5677") # Note.
while True:
socket.send_string('hello')
time.sleep(1)
Subscriber:
context = zmq.Context()
sub=context.socket(zmq.SUB) # Note.
sub.setsockopt(zmq.SUBSCRIBE, b"") # Note.
sub.connect('tcp://192.168.1.255:5677')
while True:
print(sub.recv())
[NOTE]:
You can also change the .bind() and .connect() in subscriber and publisher with your policy. (This post is relevant).
Make sure that 5677 is open in the firewall.
socket.bind("tcp://*:5677") or socket.bind("tcp://0.0.0.0:5677") is broadcasting trick.
I think the problem is that the SUB socket cannot register itself with the PUB socket. Even though in-concept the data only goes from PUB to SUB, in reality, there are also control messages (e.g. subscription topics), being sent back to the PUB.
If your netmask is 255.255.255.0, this will probably not work as expected.
I'm trying to subscribe to a pub-sub server.
When doing that using Python there is no problem, it works like expected.
But when I'm trying to subscribe to the exact same server with NodeJS ZMQ nothing happens.
I can't figure out where something goes wrong, probably at the subscribe-part?
Python:
from gzip import GzipFile
from cStringIO import StringIO
import zmq
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect("tcp://127.0.0.1:6701")
socket.setsockopt(zmq.SUBSCRIBE, '')
while True:
multipart = socket.recv_multipart()
address = multipart[0]
contents = ''.join(multipart[1:])
contents = GzipFile('','r',0,StringIO(contents)).read()
print("[%s] %s\n" % (address, contents))
socket.close()
context.term()
NodeJS:
var zmq = require('zmq')
, sock = zmq.socket('sub');
sock.connect('tcp://127.0.0.1:6701');
sock.subscribe('');
console.log('Subscriber connected to port 6701');
sock.on('message', function(topic, message) {
console.log('received a message related to:', topic, 'containing message:', message);
});
The on-message part in the NodeJS example never gets fired.
When I run a simple NodeJS publisher the subscriber works like expected.
Note that the address I connect to is a local IP due to the fact that I run some local distribution tool for the ZeroMQ messages.
What can be the difference between the two scripts that the NodeJS script does not behave like the Python script on the same publishing source?
Both are using ZeroMQ 4.
Edit:
As suggested by Jason I would post some the code of the publisher. But because this is a 3rd party I don't have the code of that. But when I fire up a simple Python publisher the subscribers act the same like they do on the 3rd party publisher.
Simple Python publisher:
import zmq
import random
import sys
import time
port = "6701"
if len(sys.argv) > 1:
port = sys.argv[1]
int(port)
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:%s" % port)
while True:
topic = random.randrange(9999,10005)
messagedata = random.randrange(1,215) - 80
print "%d %d" % (topic, messagedata)
socket.send("%d %d" % (topic, messagedata))
time.sleep(1)
NodeJS publisher:
var zmq = require('zmq')
, sock = zmq.socket('pub');
sock.bindSync('tcp://127.0.0.1:6701');
console.log('Publisher bound to port 3000');
setInterval(function(){
console.log('sending a multipart message envelope');
sock.send(['kitty cats', 'meow!']);
}, 500);
The NodeJS publisher works with both the Python and the NodeJS subscriber but the Python publisher works only with the Python subscriber and not the NodeJS one.
Fixed.
Removing node_modules and reinstaling it by npm install zmq.
I have the following Code Snippets and run both in the same VirtualBox VM. I get no error, yet I receive nothing. In wireshark, I see packets coming from my local Adress to the multicast address, but none returning.
receiver.py
import PyQt5.QtNetwork as QTN
groupaddr = QTN.QHostAddress("239.255.43.22")
udp = QTN.QUdpSocket()
udp.setSocketOption(QTN.QAbstractSocket.MulticastLoopbackOption,1)
udp.setSocketOption(QTN.QAbstractSocket.MulticastTtlOption,32)
udp.bind(QTN.QHostAddress.AnyIPv4,54555,QTN.QUdpSocket.ShareAddress)
ni = QTN.QNetworkInterface()
udp.joinMulticastGroup(groupaddr,ni)
while True:
if udp.isReadable():
data,host,port = udp.readDatagram(udp.pendingDatagramSize())
print(data)
print(host)
udp.leaveMulticastGroup(groupaddr)
udp.close()
break
sender.py
import PyQt5.QtNetwork as QTN
groupaddr = QTN.QHostAddress("239.255.43.22")
udp = QTN.QUdpSocket()
udp.setSocketOption(QTN.QAbstractSocket.MulticastLoopbackOption,1)
udp.setSocketOption(QTN.QAbstractSocket.MulticastTtlOption,32)
ni = QTN.QNetworkInterface()
udp.bind(QTN.QHostAddress.AnyIPv4,54555,QTN.QUdpSocket.ShareAddress)
udp.setMulticastInterface(ni)
udp.joinMulticastGroup(groupaddr,ni)
udp.writeDatagram("test",groupaddr,54555)
I am an idiot and should have RTFM more careful, using hasPendingDatagrams() instead of isReadable() solved it