zmq_socket_monitor.txt 9.75 KB
Newer Older
1 2
zmq_socket_monitor(3)
=====================
3 4 5 6 7


NAME
----

8
zmq_socket_monitor - monitor socket events
9 10 11 12


SYNOPSIS
--------
13
*int zmq_socket_monitor (void '*socket', char '*endpoint', int 'events');*
14 15 16 17


DESCRIPTION
-----------
18 19 20 21 22
The _zmq_socket_monitor()_ method lets an application thread track
socket events (like connects) on a ZeroMQ socket. Each call to this
method creates a 'ZMQ_PAIR' socket and binds that to the specified
inproc:// 'endpoint'. To collect the socket events, you must create
your own 'ZMQ_PAIR' socket, and connect that to the endpoint.
23

24 25 26 27 28
Note that there is also a DRAFT function linkzmq:zmq_socket_monitor_versioned[3],
which allows to subscribe to events that provide more information.
Calling zmq_socket_monitor is equivalent to calling 'zmq_socket_monitor_versioned'
with the 'event_version' parameter set to 1, with the exception of error cases.

29 30
The 'events' argument is a bitmask of the socket events you wish to
monitor, see 'Supported events' below. To monitor all events, use the
31 32 33 34
event value ZMQ_EVENT_ALL. NOTE: as new events are added, the catch-all
value will start returning them. An application that relies on a strict
and fixed sequence of events must not use ZMQ_EVENT_ALL in order to
guarantee compatibility with future versions.
35

36 37 38
Each event is sent as two frames. The first frame contains an event
number (16 bits), and an event value (32 bits) that provides additional
data according to the event number. The second frame contains a string
39
that specifies the affected endpoint.
40 41

----
42 43
The _zmq_socket_monitor()_ method supports only connection-oriented
transports, that is, TCP, IPC, and TIPC.
44
----
45

46 47
Supported events
----------------
48

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
ZMQ_EVENT_CONNECTED
~~~~~~~~~~~~~~~~~~~
The socket has successfully connected to a remote peer. The event value
is the file descriptor (FD) of the underlying network socket. Warning:
there is no guarantee that the FD is still valid by the time your code
receives this event.

ZMQ_EVENT_CONNECT_DELAYED
~~~~~~~~~~~~~~~~~~~~~~~~~
A connect request on the socket is pending. The event value is unspecified.

ZMQ_EVENT_CONNECT_RETRIED
~~~~~~~~~~~~~~~~~~~~~~~~~
A connect request failed, and is now being retried. The event value is the
reconnect interval in milliseconds. Note that the reconnect interval is
recalculated at each retry.

ZMQ_EVENT_LISTENING
~~~~~~~~~~~~~~~~~~~
The socket was successfully bound to a network interface. The event value
is the FD of the underlying network socket. Warning: there is no guarantee
that the FD is still valid by the time your code receives this event.

ZMQ_EVENT_BIND_FAILED
~~~~~~~~~~~~~~~~~~~~~
The socket could not bind to a given interface. The event value is the
errno generated by the system bind call.

ZMQ_EVENT_ACCEPTED
~~~~~~~~~~~~~~~~~~
The socket has accepted a connection from a remote peer. The event value is
the FD of the underlying network socket. Warning: there is no guarantee that
the FD is still valid by the time your code receives this event.

ZMQ_EVENT_ACCEPT_FAILED
~~~~~~~~~~~~~~~~~~~~~~~
The socket has rejected a connection from a remote peer. The event value is
the errno generated by the accept call.

ZMQ_EVENT_CLOSED
~~~~~~~~~~~~~~~~
The socket was closed. The event value is the FD of the (now closed) network
socket.

ZMQ_EVENT_CLOSE_FAILED
~~~~~~~~~~~~~~~~~~~~~~
The socket close failed. The event value is the errno returned by the system
call. Note that this event occurs only on IPC transports.

ZMQ_EVENT_DISCONNECTED
~~~~~~~~~~~~~~~~~~~~~~
The socket was disconnected unexpectedly. The event value is the FD of the
underlying network socket. Warning: this socket will be closed.

ZMQ_EVENT_MONITOR_STOPPED
~~~~~~~~~~~~~~~~~~~~~~~~~
Monitoring on this socket ended.
106

107 108 109 110 111
ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unspecified error during handshake.
The event value is an errno.

112
ZMQ_EVENT_HANDSHAKE_SUCCEEDED
113
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
114 115 116
The ZMTP security mechanism handshake succeeded.
The event value is unspecified.

117 118
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
119 120 121
The ZMTP security mechanism handshake failed due to some mechanism protocol
error, either between the ZMTP mechanism peers, or between the mechanism
server and the ZAP handler. This indicates a configuration or implementation
122
error in either peer resp. the ZAP handler.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
The event value is one of the ZMQ_PROTOCOL_ERROR_* values:
ZMQ_PROTOCOL_ERROR_ZMTP_UNSPECIFIED
ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND
ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_SEQUENCE
ZMQ_PROTOCOL_ERROR_ZMTP_KEY_EXCHANGE
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_UNSPECIFIED
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_MESSAGE
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_READY
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_WELCOME
ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_METADATA
ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC
ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH
ZMQ_PROTOCOL_ERROR_ZAP_UNSPECIFIED
ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY
ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID
ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION
ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE
ZMQ_PROTOCOL_ERROR_ZAP_INVALID_METADATA
144 145 146 147

ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ZMTP security mechanism handshake failed due to an authentication failure.
148
The event value is the status code returned by the ZAP handler (i.e. 300,
149 150 151
400 or 500).


152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

RETURN VALUE
------------
The _zmq_socket_monitor()_ function returns a value of 0 or greater if
successful. Otherwise it returns `-1` and sets 'errno' to one of the values
defined below.


ERRORS
------
*ETERM*::
The 0MQ 'context' associated with the specified 'socket' was terminated.

*EPROTONOSUPPORT*::
The requested 'transport' protocol is not supported. Monitor sockets are
required to use the inproc:// transport.

*EINVAL*::
The endpoint supplied is invalid.

EXAMPLE
-------
174
.Monitoring client and server sockets
175
----
176 177 178
//  Read one event off the monitor socket; return value and address
//  by reference, if not null, and event number by value. Returns -1
//  in case of error.
179

180 181
static int
get_monitor_event (void *monitor, int *value, char **address)
182
{
183 184 185 186
    //  First frame in message contains event number and value
    zmq_msg_t msg;
    zmq_msg_init (&msg);
    if (zmq_msg_recv (&msg, monitor, 0) == -1)
J.T. Conklin's avatar
J.T. Conklin committed
187
        return -1;              //  Interrupted, presumably
188 189 190 191 192 193 194 195 196 197
    assert (zmq_msg_more (&msg));

    uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
    uint16_t event = *(uint16_t *) (data);
    if (value)
        *value = *(uint32_t *) (data + 2);

    //  Second frame in message contains event address
    zmq_msg_init (&msg);
    if (zmq_msg_recv (&msg, monitor, 0) == -1)
J.T. Conklin's avatar
J.T. Conklin committed
198
        return -1;              //  Interrupted, presumably
199 200 201 202 203 204 205
    assert (!zmq_msg_more (&msg));

    if (address) {
        uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
        size_t size = zmq_msg_size (&msg);
        *address = (char *) malloc (size + 1);
        memcpy (*address, data, size);
206
        (*address)[size] = 0;
207 208
    }
    return event;
209 210
}

211
int main (void)
212
{
213 214
    void *ctx = zmq_ctx_new ();
    assert (ctx);
215

216 217 218 219 220
    //  We'll monitor these two sockets
    void *client = zmq_socket (ctx, ZMQ_DEALER);
    assert (client);
    void *server = zmq_socket (ctx, ZMQ_DEALER);
    assert (server);
221

222 223 224 225
    //  Socket monitoring only works over inproc://
    int rc = zmq_socket_monitor (client, "tcp://127.0.0.1:9999", 0);
    assert (rc == -1);
    assert (zmq_errno () == EPROTONOSUPPORT);
226

227 228 229 230
    //  Monitor all events on client and server sockets
    rc = zmq_socket_monitor (client, "inproc://monitor-client", ZMQ_EVENT_ALL);
    assert (rc == 0);
    rc = zmq_socket_monitor (server, "inproc://monitor-server", ZMQ_EVENT_ALL);
231
    assert (rc == 0);
232

233 234 235 236 237
    //  Create two sockets for collecting monitor events
    void *client_mon = zmq_socket (ctx, ZMQ_PAIR);
    assert (client_mon);
    void *server_mon = zmq_socket (ctx, ZMQ_PAIR);
    assert (server_mon);
238

239 240
    //  Connect these to the inproc endpoints so they'll get events
    rc = zmq_connect (client_mon, "inproc://monitor-client");
241
    assert (rc == 0);
242
    rc = zmq_connect (server_mon, "inproc://monitor-server");
243
    assert (rc == 0);
244

245 246
    //  Now do a basic ping test
    rc = zmq_bind (server, "tcp://127.0.0.1:9998");
247
    assert (rc == 0);
248
    rc = zmq_connect (client, "tcp://127.0.0.1:9998");
249
    assert (rc == 0);
250 251 252 253 254 255 256 257 258 259 260 261
    bounce (client, server);

    //  Close client and server
    close_zero_linger (client);
    close_zero_linger (server);

    //  Now collect and check events from both sockets
    int event = get_monitor_event (client_mon, NULL, NULL);
    if (event == ZMQ_EVENT_CONNECT_DELAYED)
        event = get_monitor_event (client_mon, NULL, NULL);
    assert (event == ZMQ_EVENT_CONNECTED);
    event = get_monitor_event (client_mon, NULL, NULL);
262 263
    assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
    event = get_monitor_event (client_mon, NULL, NULL);
264 265 266 267 268 269 270 271
    assert (event == ZMQ_EVENT_MONITOR_STOPPED);

    //  This is the flow of server events
    event = get_monitor_event (server_mon, NULL, NULL);
    assert (event == ZMQ_EVENT_LISTENING);
    event = get_monitor_event (server_mon, NULL, NULL);
    assert (event == ZMQ_EVENT_ACCEPTED);
    event = get_monitor_event (server_mon, NULL, NULL);
272 273
    assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
    event = get_monitor_event (server_mon, NULL, NULL);
274 275 276 277 278 279 280 281
    assert (event == ZMQ_EVENT_CLOSED);
    event = get_monitor_event (server_mon, NULL, NULL);
    assert (event == ZMQ_EVENT_MONITOR_STOPPED);

    //  Close down the sockets
    close_zero_linger (client_mon);
    close_zero_linger (server_mon);
    zmq_ctx_term (ctx);
282

283 284
    return 0 ;
}
285 286 287 288 289 290 291 292 293 294
----


SEE ALSO
--------
linkzmq:zmq[7]


AUTHORS
-------
295 296
This page was written by the 0MQ community. To make a change please
read the 0MQ Contribution Policy at <http://www.zeromq.org/docs:contributing>.