Menu

Correct way to handle disconnection with req reply

2019-11-20
2019-11-26
  • Mark Garnett

    Mark Garnett - 2019-11-20

    Hi all,

    I am new to ZMQ but fairly experienced with TCP , UDP, network streams in LabVIEW. I'm looking at the trivial request/reply example. So from what I see you just open the socket, do your work in a loop, and then kill the socket when terminating the loop and shutting down

    My question is, what do you do about error handling? If I was using TCP, I would have a little state machine in the loop, with 3 states:

    listen : uses TCP Listen and waits with timeout for incoming connections. Return to TCP listen if no connections, otherwise transition to "receive" state
    receive: reads data off the TCP port with timeout. or no data If there is an error, goto state "handle error" otherwise stay in receive. Assumes a heartbeat message of somekind is coming thorugh.

    handle error: cleans up the socket reference and opens a new one. Goes to "listen state"

    This kind of pattern has worked fine for me in the past, allowing disconnections, reconnections without problems. So for ZMQ, if I get an error on my receive function, do I need to kill the socket and reopen one like with TCP? Or is that handled "behind the scenes"?

    Regards,
    Mark Garnett

     
  • Martijn Jasperse

    Hi Mark,
    To (over)simplify, ZMQ handles all that in the background. It is a bit hard to get your head around if you're used to TCP because most of it comes from the framework of many-to-many network topology, so I'd recommend reading the "guide" for details. To summarize the main differences as I see them

    • Connect/disconnect is handled in the background; this is hidden from the application (although "socket_monitor" exists if you need to know about it)
    • Bind and Listen return immediately, even if no connection has occurred (yet)
    • Messages are queued internally for when connection is made or reestablished (see "HWM")
    • The only errors you should expect from receive are "timeout" or "terminate" (or maybe EFSM if you're using a strict protocol)

    If you're interested in reliable point-to-point connections, look into the "pirate patterns". I included an example as part of the package.

    In some sense ZMQ is overkill for point-to-point, but it is directly extensible for more general message processing in a way that becomes complicated when using TCP directly. PUB/SUB is a popular and simple such use, brokering/balancing is a more complex one.

    Cheers,
    Martijn

     
  • Mark Garnett

    Mark Garnett - 2019-11-21

    Thank you Martijn, this is good. I have not dived deeply into the guide yet. Is there a way to disable buffering or set the max buffer size?

     
  • Martijn Jasperse

    Yes, this is referred to as the "high water mark" in the documentation. You should be able to use zmq_setsockopt to set ZMQ_RCVHWM and/or ZMQ_SNDHWM to 1. This must be done on the socket after creation but before connect/bind.

    Looks like there's a new option called ZMQ_CONFLATE but it seems that interacts badly with multipart messages so it's probably not preferable.

     

Log in to post a comment.