123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- zmq_socket_monitor_versioned(3)
- ===============================
- NAME
- ----
- zmq_socket_monitor_versioned - monitor socket events
- SYNOPSIS
- --------
- *int zmq_socket_monitor_versioned (void '*socket', char '*endpoint', uint64_t 'events', int 'event_version', int 'type');*
- *int zmq_socket_monitor_pipes_stats (void '*socket');*
- DESCRIPTION
- -----------
- The _zmq_socket_monitor_versioned()_ 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.
- The 'events' argument is a bitmask of the socket events you wish to
- monitor, see 'Supported events' below. To monitor all events for a version, use
- the event value ZMQ_EVENT_ALL_V<version>, e.g. ZMQ_EVENT_ALL_V1. For non-DRAFT event
- versions, this value will not change in the future, so new event types will only be
- added in new versions (note that this is a change over zmq_socket_monitor and the
- unversioned ZMQ_EVENT_ALL).
- Note that event_version 2 is currently in DRAFT mode. The protocol may be
- changed at any time for event_versions in DRAFT.
- ZMQ_CURRENT_EVENT_VERSION and ZMQ_CURRENT_EVENT_VERSION_DRAFT are always defined
- to the most recent stable or DRAFT event version, which are currently 1 resp. 2
- This page describes the protocol for 'event_version' 2 only. For the protocol
- used with 'event_version' 1, please refer to linkzmq:zmq_socket_monitor[3].
- Each event is sent in multiple frames. The first frame contains an event
- number (64 bits). The number and content of further frames depend on this
- event number.
- Unless it is specified differently, the second frame contains the number of
- value frames that will follow it as a 64 bits integer. The third frame to N-th
- frames contain an event value (64 bits) that provides additional data according
- to the event number. Each event type might have a different number of values.
- The second-to-last and last frames contain strings that specifies the affected
- connection or endpoint. The former frame contains a string denoting the local
- endpoint, while the latter frame contains a string denoting the remote endpoint.
- Either of these may be empty, depending on the event type and whether the
- connection uses a bound or connected local endpoint.
- Note that the format of the second and further frames, and also the number of
- frames, may be different for events added in the future.
- The 'type' argument is used to specify the type of the monitoring socket.
- Supported types are 'ZMQ_PAIR', 'ZMQ_PUB' and 'ZMQ_PUSH'. Note that consumers
- of the events will have to be compatible with the socket type, for instance a
- monitoring socket of type 'ZMQ_PUB' will require consumers of type 'ZMQ_SUB'.
- In the case that the monitoring socket type is of 'ZMQ_PUB', the multipart
- message topic is the event number, thus consumers should subscribe to the
- events they want to receive.
- The _zmq_socket_monitor_pipes_stats()_ method triggers an event of type
- ZMQ_EVENT_PIPES_STATS for each connected peer of the monitored socket.
- NOTE: _zmq_socket_monitor_pipes_stats()_ is in DRAFT state.
- ----
- Monitoring events are only generated by some transports: At the moment these
- are SOCKS, TCP, IPC, and TIPC. Note that it is not an error to call
- 'zmq_socket_monitor_versioned' on a socket that is connected or bound to some
- other transport, as this may not be known at the time
- 'zmq_socket_monitor_versioned' is called. Also, a socket can be connected/bound
- to multiple endpoints using different transports.
- ----
- Supported events (v1)
- ----------------
- 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 for 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.
- ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Unspecified error during handshake.
- The event value is an errno.
- ZMQ_EVENT_HANDSHAKE_SUCCEEDED
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The ZMTP security mechanism handshake succeeded.
- The event value is unspecified.
- ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 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
- error in either peer resp. the ZAP handler.
- 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
- ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The ZMTP security mechanism handshake failed due to an authentication failure.
- The event value is the status code returned by the ZAP handler (i.e. 300,
- 400 or 500).
- ----
- Supported events (v2)
- ----------------
- ZMQ_EVENT_PIPE_STATS
- ~~~~~~~~~~~~~~~~~~~~
- This event provides two values, the number of messages in each of the two
- queues associated with the returned endpoint (respectively egress and ingress).
- This event only triggers after calling the function
- _zmq_socket_monitor_pipes_stats()_.
- NOTE: this measurement is asynchronous, so by the time the message is received
- the internal state might have already changed.
- NOTE: when the monitored socket and the monitor are not used in a poll, the
- event might not be delivered until an API has been called on the monitored
- socket, like zmq_getsockopt for example (the option is irrelevant).
- NOTE: in DRAFT state, not yet available in stable releases.
- RETURN VALUE
- ------------
- The _zmq_socket_monitor()_ and _zmq_socket_monitor_pipes_stats()_ functions
- return a value of 0 or greater if successful. Otherwise they return `-1` and
- set 'errno' to one of the values defined below.
- ERRORS - _zmq_socket_monitor()_
- -------------------------------
- *ETERM*::
- The 0MQ 'context' associated with the specified 'socket' was terminated.
- *EPROTONOSUPPORT*::
- The transport protocol of the monitor 'endpoint' is not supported. Monitor
- sockets are required to use the inproc:// transport.
- *EINVAL*::
- The monitor 'endpoint' supplied does not exist or the specified socket 'type'
- is not supported.
- ERRORS - _zmq_socket_monitor_pipes_stats()_
- -------------------------------------------
- *ENOTSOCK*::
- The 'socket' parameter was not a valid 0MQ socket.
- *EINVAL*::
- The socket did not have monitoring enabled.
- *EAGAIN*::
- The monitored socket did not have any connections to monitor yet.
- EXAMPLE
- -------
- .Monitoring client and server sockets
- ----
- // Read one event off the monitor socket; return values and addresses
- // by reference, if not null, and event number by value. Returns -1
- // in case of error.
- static uint64_t
- get_monitor_event (void *monitor, uint64_t *value, char **local_address, char **remote_address)
- {
- // First frame in message contains event number
- zmq_msg_t msg;
- zmq_msg_init (&msg);
- if (zmq_msg_recv (&msg, monitor, 0) == -1)
- return -1; // Interrupted, presumably
- assert (zmq_msg_more (&msg));
- uint64_t event;
- memcpy (&event, zmq_msg_data (&msg), sizeof (event));
- zmq_msg_close (&msg);
- // Second frame in message contains the number of values
- zmq_msg_init (&msg);
- if (zmq_msg_recv (&msg, monitor, 0) == -1)
- return -1; // Interrupted, presumably
- assert (zmq_msg_more (&msg));
- uint64_t value_count;
- memcpy (&value_count, zmq_msg_data (&msg), sizeof (value_count));
- zmq_msg_close (&msg);
- for (uint64_t i = 0; i < value_count; ++i) {
- // Subsequent frames in message contain event values
- zmq_msg_init (&msg);
- if (zmq_msg_recv (&msg, monitor, 0) == -1)
- return -1; // Interrupted, presumably
- assert (zmq_msg_more (&msg));
- if (value_ && value_ + i)
- memcpy (value_ + i, zmq_msg_data (&msg), sizeof (*value_));
- zmq_msg_close (&msg);
- }
- // Second-to-last frame in message contains local address
- zmq_msg_init (&msg);
- if (zmq_msg_recv (&msg, monitor, 0) == -1)
- return -1; // Interrupted, presumably
- assert (zmq_msg_more (&msg));
- if (local_address_) {
- uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
- size_t size = zmq_msg_size (&msg);
- *local_address_ = (char *) malloc (size + 1);
- memcpy (*local_address_, data, size);
- (*local_address_)[size] = 0;
- }
- zmq_msg_close (&msg);
- // Last frame in message contains remote address
- zmq_msg_init (&msg);
- if (zmq_msg_recv (&msg, monitor, 0) == -1)
- return -1; // Interrupted, presumably
- assert (!zmq_msg_more (&msg));
- if (remote_address_) {
- uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
- size_t size = zmq_msg_size (&msg);
- *remote_address_ = (char *) malloc (size + 1);
- memcpy (*remote_address_, data, size);
- (*remote_address_)[size] = 0;
- }
- zmq_msg_close (&msg);
- return event;
- }
- int main (void)
- {
- void *ctx = zmq_ctx_new ();
- assert (ctx);
- // We'll monitor these two sockets
- void *client = zmq_socket (ctx, ZMQ_DEALER);
- assert (client);
- void *server = zmq_socket (ctx, ZMQ_DEALER);
- assert (server);
- // Socket monitoring only works over inproc://
- int rc = zmq_socket_monitor_versioned (client, "tcp://127.0.0.1:9999", 0, 2);
- assert (rc == -1);
- assert (zmq_errno () == EPROTONOSUPPORT);
- // Monitor all events on client and server sockets
- rc = zmq_socket_monitor_versioned (client, "inproc://monitor-client", ZMQ_EVENT_ALL, 2);
- assert (rc == 0);
- rc = zmq_socket_monitor_versioned (server, "inproc://monitor-server", ZMQ_EVENT_ALL, 2);
- assert (rc == 0);
- // 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);
- // Connect these to the inproc endpoints so they'll get events
- rc = zmq_connect (client_mon, "inproc://monitor-client");
- assert (rc == 0);
- rc = zmq_connect (server_mon, "inproc://monitor-server");
- assert (rc == 0);
- // Now do a basic ping test
- rc = zmq_bind (server, "tcp://127.0.0.1:9998");
- assert (rc == 0);
- rc = zmq_connect (client, "tcp://127.0.0.1:9998");
- assert (rc == 0);
- 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);
- 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);
- 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);
- return 0 ;
- }
- ----
- SEE ALSO
- --------
- linkzmq:zmq[7]
- AUTHORS
- -------
- 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>.
|