pynng
pynng copied to clipboard
Pair1 example extended
while learning about Pair1, I played with the example a bit, providing some extra examples and tests. Thought it might be nice to share that code so....
#from the docs page https://pynng.readthedocs.io/en/latest/core.html#available-protocols
# with some mods
# Pair1 allows single Server/Listener to connect bi-directionally with multiple Client/Dialers
# it does NOT operate as a Publisher in that a listner.send() goes to ??
import sys, traceback
from pynng import Pair1, Timeout
print("begin Pair 1 polyamorous test")
address = 'tcp://127.0.0.1:12343'
with Pair1(listen=address, polyamorous=True, recv_timeout=100) as s0, \
Pair1(dial=address, polyamorous=True, recv_timeout=100) as s1, \
Pair1(dial=address, polyamorous=True, recv_timeout=100) as s2:
print("opened all 3")
s0.send(b'hi everybody!')
s1.send(b'hello from s1')
s2.send(b'hello from s2')
print("sent all three")
print("recv_msg on s0")
msg1 = s0.recv_msg()
print(msg1.bytes) # prints b'hello from s1'
msg2 = s0.recv_msg()
print(msg2.bytes) # prints b'hello from s2'
print("recv on s1:")
msg01 = s1.recv()
print(msg01) # prints b'hello from s1'
try:
print("recv on s2")
msg02 = s2.recv()
print(msg02) # prints b'hello from s2'
except Timeout:
print("Timeout on S2 waiting to hear from s0")
print("send single msg responses")
msg1.pipe.send(b'hey s1')
msg2.pipe.send(b'hey s2')
print(s2.recv()) # prints b'hey s2'
print(s1.recv()) # prints b'hey s1'
# beyond first msg, repeats will share the Pipe but not data
s1.send(b'more from s1')
morMsg = s0.recv_msg()
print("morMsg: ")
print(morMsg.bytes)
if morMsg.pipe == msg1.pipe:
print ("msg1 and morMsg share pipe")
else:
print ("msg1 and morMsg do NOT share pipe")
print("and msg1 still says:")
print(msg1.bytes)
print("what if s0 does recv instead of recvMsg?")
s1.send(b'again from s1')
more = s0.recv()
print(more)
# print("It works, we just dont get the Message info")
print("Pair1 with both listen and dial should throw exception")
# pynng Pair1 has no code to recognize this error, allowing both arguments
# however the underlying Socket should throw an AddressInUse exception
try:
with Pair1(dial=address, listen=address, polyamorous=True, recv_timeout=100) as s3:
s3.send(b'hello out there')
msg = s0.recv_msg()
print("rceve on s0")
print(msg.bytes)
s3.send(b'hello out there')
msg = s3.recv_msg()
print("rceve on s3")
print(msg.bytes)
except:
print("caught something", sys.exc_info()[0])
traceback.print_exc()#sys.exc_info()[2].print_tb()
#raise
print("End Pair1 test")
Hi @MauiJerry, thanks for your interest in the library and for opening an issue. You've got a good point that the docs could make it more clear what a polyamorous pair socket does when you call send
on the socket instead of a pipe.
Probably when using a polyamorous pair socket that has multiple connections socket.send()
shouldn't be called, since it's hard to reason about where it goes. Using recv_msg()
and then calling msg.pipe.send()
like you've done is a great strategy. Alternatively, you can access a list of active pipes via socket.pipes
directly, and use the remote_address
property of the pipe to see who the remote node is.
P. S., I made a small edit to your post to make the code format as python.
Thanks... nice to see the python technique for sharing code here. I'll try to remember it. I have this working nicely on my rPi project, with a PubSub channel sending out updates from Server, that listens on the Pair1 ... although it currently only works using 127.... fixed address. on my TODO is getting zeroconfig working so i can use a name in my code and have the clients on PC.