Reputation:
I have a python program which sends height data from my client to my server program. My server program will not be always running so if I don't recieve a response I would like it to try again.
So far what I have is that if a response (from the server) is not given in 20 Seconds it causes an exception and recalls my input. It works fine until I try it a second time.
Here is my code:
import zmq
from time import sleep
global radius
context = zmq.Context()
print("Remote Deployment Application")
print("Lightweight ZMQ Communication")
print("Connecting to Desk Ctrl Service")
socket = context.socket(zmq.REQ)
socket.connect("tcp://192.168.1.9:5555")
socket.setsockopt(zmq.RCVTIMEO, 30000)
socket.setsockopt(zmq.LINGER, 0)
# Do 10 requests,waiting each time for a response
def __init__(self, height):
self.height = height
def start():
global height
height = input("Enter in request: ")
SendHeightVal()
def SendHeightVal():
global userinput
global height
print("Sent Request. Awaiting Reply.")
so_bytes = height.encode()
socket.send(so_bytes)
so_bytes = 0
try:
message = socket.recv()
except:
print("Something went wrong. No response from server!")
message = None
start()
print(message)
start()
Here is the error:
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "client.py", line 44, in <module>
start()
File "client.py", line 22, in start
SendHeightVal()
File "client.py", line 37, in SendHeightVal
start()
File "client.py", line 22, in start
SendHeightVal()
File "client.py", line 30, in SendHeightVal
socket.send(so_bytes)
File "/usr/local/lib/python3.6/site-packages/zmq/sugar/socket.py", line 391, in send
return super(Socket, self).send(data, flags=flags, copy=copy, track=track)
File "zmq/backend/cython/socket.pyx", line 727, in zmq.backend.cython.socket.Socket.send
File "zmq/backend/cython/socket.pyx", line 774, in zmq.backend.cython.socket.Socket.send
File "zmq/backend/cython/socket.pyx", line 249, in zmq.backend.cython.socket._send_copy
File "zmq/backend/cython/socket.pyx", line 244, in zmq.backend.cython.socket._send_copy
File "zmq/backend/cython/checkrc.pxd", line 25, in zmq.backend.cython.checkrc._check_rc
zmq.error.ZMQError: Operation cannot be accomplished in current state
Upvotes: 2
Views: 1802
Reputation: 1
Let's start with a simple inventory of mandatory features:
[agent-A] sends height data from my client to my server program. My server program [agent-B] will not be always running so if I don't receive a response I would like it [agent-A] to try again.
For this, the REQ/REP
hard-wired two-step of
[A].send()-[B].recv()-[B].send()-[A].recv()-[A].send()-[B].recv()-...
is not the promising or safe choice.
1 ) always set zmq.LINGER = 0
to avoid zombies & hangups ( +1 for doing that )
2 ) if need not keep all [A]-side data delivered, may enjoy zmq.IMMEDIATE
to deliver only to live [B] and zmq.CONFLATE
to deliver only the most "fresh" values the [A]-side did .send()
3 ) if need in a need to keep all [A]-side data delivered, will have to either re-factor the strategy of sending on [A]-side become robust to missing [B]-side, so as to avoid blind and just optimistic data-pumping into the Context()
-instance controlled, but rather expensive and quite limited resources, or carefully plan and pre-allocate due capacities, so as to remain able to internally store all of them till the [B]-comes ( or not ) somewhere unsure in the future or the [A]-side dropping or blocking or exceptions will be unavoidable.
4 ) never expect the built-in trivial ( primitive ) archetypes to match your production needs, these come as a sort of LEGO-building blocks for some smarter, problem-specific distributed signalling and messaging infrastructure, not as a magic wand to solve all properties ( principally unknown and undefined at the time of these primitive-tools implementation ), so more engineering efforts will come, as one moves outside of school-book examples into designing robust distributed systems. Here could be a way using a composition of { PUSH/PULL + PULL/PUSH | PAIR/PAIR | XREQ/XREP }
plus heart-beating watchdog and re-discovery of remote agent(s). Some other archetypes may get later added for N+1 fault resilience or performance boosting with workload balancers or remote-console or latency motivated off-site remote-logging - if needed, all depending on hell many details that are beyond the initial post or a few SLOCs.
5 ) always handle exceptions, even if "masters" tell you one need not do that. Why? In distributed-system any problem cease to be a just-local issue, so unhandled exceptions, fallen into a silent death of some agent will result in global impacts of missing such agent ( many ) others do rely on and may easily got blocked without any local-reason visible to 'em.
6 ) in production domain, there will be more efforts needed for protecting any smart infrastructure from remote-failures and also DoS-alike events, that impact local-Context()
SPOF, so the distributed-system architecture design is both very interesting and quite demanding domain.
Upvotes: 1
Reputation: 1465
Check this, you will find this:
socket zmq.REQ will block on send unless it has successfully received a reply back.
Which means that you cannot send another request until receiving an answer. ZMQ has different messaging patterns the one you are using Client / Server zmq.REQ
/ zmq.REP
.
Any attempt to send another message to the socket (zmq.REQ/zmq.REP), without having received a reply/request will result in an error:
....
socket.send ("Hello")
socket.send ("Hello1")
....
Error: zmq.core.error.ZMQError: Operation cannot be accomplished in current state
That's why your are getting the exception:
zmq.error.ZMQError: Operation cannot be accomplished in current state
Upvotes: 0