ZMQ REP Message Sink: Difference between revisions

From GNU Radio
Jump to navigation Jump to search
(add information about Zeromq restrictions)
(add note about IP addresses)
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
[[Category:Block Docs]]
[[Category:Block Docs]]
The ZMQ REP Message Sink block receives async messages and sends them to a ZMQ REP socket. This block will connect to a ZMQ REQ Message Source <b>only</b>.<br>
The ZMQ REP Message Sink block receives async messages and sends them to a ZMQ REP socket. This block will connect to a ZMQ REQ Message Source.<br>
The zeromq.org website says:<br>
The zeromq.org website says:<br>
"The REQ-REP socket pair is in lockstep. The client issues zmq_send() and then zmq_recv(), in a loop (or once if that's all it needs). Doing any other sequence (e.g., sending two messages in a row) will result in a return code of -1 from the send or recv call. Similarly, the service issues zmq_recv() and then zmq_send() in that order, as often as it needs to."<br>
"The REQ-REP socket pair is in lockstep. The client issues zmq_send() and then zmq_recv(), in a loop (or once if that's all it needs). Doing any other sequence (e.g., sending two messages in a row) will result in a return code of -1 from the send or recv call." Likewise, the server "issues zmq_recv() and then zmq_send() in that order, as often as it needs to."<br>
That happens on a single port. Apparently the gr-zeromq implementation of ZMQ REQ Message Source and ZMQ REP Message Sink do not require that message flow. On a flowgraph, a message feed such as a Message Strobe block can send to a ZMQ REP Message Sink on a continuous basis. Similarly, a ZMQ REQ Message Source can receive a continuous succession of messages with no errors.<br>
Because of the zeromq.org restriction, apparently there is no way an external process can communicate with the GR implementation.


== Parameters ==
== Parameters ==
Line 11: Line 9:
; Address
; Address
: ZMQ socket address specifier. The format of the address is <code>tcp://*:port</code> where * should be 127.0.0.1 for localhost.<br>
: ZMQ socket address specifier. The format of the address is <code>tcp://*:port</code> where * should be 127.0.0.1 for localhost.<br>
: <b>Note:</b> If the Source and Sink blocks are on two different computers on the same LAN, then the IP and port number of the Sink block must be specified on each end of that connection. For example, if the Sink is on IP 192.168.2.14:5678 and the Source is on IP 192.168.2.5, both Source and Sink blocks must specify the Sink IP and port (192.168.2.14:5678).


; Timeout
; Timeout
Line 16: Line 15:


== Example Flowgraph ==
== Example Flowgraph ==
=== Inter-flowgraph ===
Request/Reply pairs can be used on one, or two separate, flowgraphs to exchange messages.<br>


[[File:REQ_REP_msg_demo_fg.png]]
[[File:REQ_REP_msg_demo_fg.png]]
=== External Python client (receive only) ===
An external Python program can receive messages from a ZMQ REP Message Sink block. An example flowgraph and Python code follow.<br>
[[File:Msg_test6_fg.png]]
The Python client code looks like this:<br>
<pre>
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#  The REQest / REPly nomenclature of the GNU Radio message blocks is from
#  the perspective of the flowgraph. So, to send a 'request' to GNU Radio, the message
#  must be sent as a 'reply' from the Python client, Likewise, a 'reply' from GNU Radio
#  must be received as a 'request' to the Python client! Therefore, send on the reply socket
#  and receive on the request socket.
#
#  The zeromq.org website says:
#  "The REQ-REP socket pair is in lockstep. The client issues zmq_send() and then zmq_recv(),
#  in a loop (or once if that's all it needs). Doing any other sequence (e.g., sending two messages in a row)
#  will result in a return code of -1 from the send or recv call." Likewise, the server "issues zmq_recv()
#  and then zmq_send() in that order, as often as it needs to."
#
#  To conform to that requirement, a non-standard "kludge" is used (see below).
import zmq
import pmt
def main():
    zmq_context = zmq.Context()
    zmq_sock = zmq_context.socket(zmq.REQ)
    zmq_sock.connect("tcp://127.0.0.1:50247")
    while(True):
        zmq_sock.send_string("\x01\x00\x00\x00")    # this is the non-standard "kludge"
        msg = zmq_sock.recv()
        print (pmt.to_python(pmt.deserialize_str(msg)))
if __name__ == '__main__':
    main()
</pre>
=== GNU Radio as a server ===
If the GNU Radio flowgraph(s) is configured as a server, the REQ message is processed by the flowgraph and a message is sent back in a REP message as the response. See [[ZMQ_REQ_Message_Source#GNU_Radio_as_a_server]] for details.


== Source Files ==
== Source Files ==

Latest revision as of 15:25, 26 March 2020

The ZMQ REP Message Sink block receives async messages and sends them to a ZMQ REP socket. This block will connect to a ZMQ REQ Message Source.
The zeromq.org website says:
"The REQ-REP socket pair is in lockstep. The client issues zmq_send() and then zmq_recv(), in a loop (or once if that's all it needs). Doing any other sequence (e.g., sending two messages in a row) will result in a return code of -1 from the send or recv call." Likewise, the server "issues zmq_recv() and then zmq_send() in that order, as often as it needs to."

Parameters

(R): Run-time adjustable

Address
ZMQ socket address specifier. The format of the address is tcp://*:port where * should be 127.0.0.1 for localhost.
Note: If the Source and Sink blocks are on two different computers on the same LAN, then the IP and port number of the Sink block must be specified on each end of that connection. For example, if the Sink is on IP 192.168.2.14:5678 and the Source is on IP 192.168.2.5, both Source and Sink blocks must specify the Sink IP and port (192.168.2.14:5678).
Timeout
Socket timeout in milliseconds, default is 100ms.

Example Flowgraph

Inter-flowgraph

Request/Reply pairs can be used on one, or two separate, flowgraphs to exchange messages.

REQ REP msg demo fg.png

External Python client (receive only)

An external Python program can receive messages from a ZMQ REP Message Sink block. An example flowgraph and Python code follow.

Msg test6 fg.png

The Python client code looks like this:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

#   The REQest / REPly nomenclature of the GNU Radio message blocks is from
#   the perspective of the flowgraph. So, to send a 'request' to GNU Radio, the message
#   must be sent as a 'reply' from the Python client, Likewise, a 'reply' from GNU Radio
#   must be received as a 'request' to the Python client! Therefore, send on the reply socket
#   and receive on the request socket.
#
#   The zeromq.org website says:
#   "The REQ-REP socket pair is in lockstep. The client issues zmq_send() and then zmq_recv(),
#   in a loop (or once if that's all it needs). Doing any other sequence (e.g., sending two messages in a row)
#   will result in a return code of -1 from the send or recv call." Likewise, the server "issues zmq_recv() 
#   and then zmq_send() in that order, as often as it needs to."
#
#   To conform to that requirement, a non-standard "kludge" is used (see below).

import zmq
import pmt

def main():
    zmq_context = zmq.Context()
    zmq_sock = zmq_context.socket(zmq.REQ)
    zmq_sock.connect("tcp://127.0.0.1:50247")
    while(True):
         zmq_sock.send_string("\x01\x00\x00\x00")    # this is the non-standard "kludge"
         msg = zmq_sock.recv()
         print (pmt.to_python(pmt.deserialize_str(msg)))
if __name__ == '__main__':
    main()

GNU Radio as a server

If the GNU Radio flowgraph(s) is configured as a server, the REQ message is processed by the flowgraph and a message is sent back in a REP message as the response. See ZMQ_REQ_Message_Source#GNU_Radio_as_a_server for details.

Source Files

C++ files
TODO
Header files
TODO
Public header files
TODO
Block definition
TODO