mirror of
https://github.com/zeromq/libzmq.git
synced 2025-01-19 08:46:44 +01:00
Merge pull request #1577 from hintjens/master
Various cleanups for CLIENT-SERVER sockets
This commit is contained in:
commit
fb57110b94
@ -10,9 +10,9 @@ if(APPLE)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
option(WITH_TWEETNACL "Build with tweetnacl" OFF)
|
||||
option(WITH_TWEETNACL "Build with tweetnacl" OFF)
|
||||
else()
|
||||
option(WITH_TWEETNACL "Build with tweetnacl" ON)
|
||||
option(WITH_TWEETNACL "Build with tweetnacl" ON)
|
||||
endif()
|
||||
|
||||
if(WITH_TWEETNACL)
|
||||
@ -23,7 +23,7 @@ if(WITH_TWEETNACL)
|
||||
)
|
||||
|
||||
set(TWEETNACL_SOURCES
|
||||
tweetnacl/src/tweetnacl.c
|
||||
tweetnacl/src/tweetnacl.c
|
||||
)
|
||||
if(WIN32)
|
||||
else()
|
||||
@ -157,6 +157,7 @@ check_function_exists(gethrtime HAVE_GETHRTIME)
|
||||
set(CMAKE_REQUIRED_INCLUDES )
|
||||
|
||||
add_definitions(-D_REENTRANT -D_THREAD_SAFE)
|
||||
add_definitions(-D_USING_CMAKE)
|
||||
|
||||
option(ENABLE_EVENTFD "Enable/disable eventfd" ZMQ_HAVE_EVENTFD)
|
||||
|
||||
|
@ -6,6 +6,7 @@ MAN3 = zmq_bind.3 zmq_unbind.3 zmq_connect.3 zmq_disconnect.3 zmq_close.3 \
|
||||
zmq_msg_init.3 zmq_msg_init_data.3 zmq_msg_init_size.3 \
|
||||
zmq_msg_move.3 zmq_msg_copy.3 zmq_msg_size.3 zmq_msg_data.3 zmq_msg_close.3 \
|
||||
zmq_msg_send.3 zmq_msg_recv.3 \
|
||||
zmq_msg_routing_id.3 zmq_msg_set_routing_id.3 \
|
||||
zmq_send.3 zmq_recv.3 zmq_send_const.3 \
|
||||
zmq_msg_get.3 zmq_msg_set.3 zmq_msg_more.3 zmq_msg_gets.3 \
|
||||
zmq_getsockopt.3 zmq_setsockopt.3 \
|
||||
|
@ -688,6 +688,17 @@ Default value:: 0 (leave to OS default)
|
||||
Applicable socket types:: all, when using TCP transports.
|
||||
|
||||
|
||||
ZMQ_THREADSAFE: Retrieve socket thread safety
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The 'ZMQ_THREADSAFE' option shall retrieve a boolean value indicating whether
|
||||
or not the socket is threadsafe. Currently only 'ZMQ_CLIENT' sockets are
|
||||
threadsafe.
|
||||
|
||||
[horizontal]
|
||||
Option value type:: boolean
|
||||
Applicable socket types:: all
|
||||
|
||||
|
||||
ZMQ_TOS: Retrieve the Type-of-Service socket override status
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Retrieve the IP_TOS option for the socket.
|
||||
|
61
doc/zmq_msg_routing_id.txt
Normal file
61
doc/zmq_msg_routing_id.txt
Normal file
@ -0,0 +1,61 @@
|
||||
zmq_msg_routing_id(3)
|
||||
=====================
|
||||
|
||||
|
||||
NAME
|
||||
----
|
||||
zmq_msg_routing_id - return routing ID for message, if any
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
*uint32_t zmq_msg_routing_id (zmq_msg_t '*message');*
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
The _zmq_msg_routing_id()_ function returns the routing ID for the message,
|
||||
if any. The routing ID is set on all messages received from a 'ZMQ_SERVER'
|
||||
socket. To send a message to a 'ZMQ_SERVER' socket you must set the routing
|
||||
ID of a connected 'ZMQ_CLIENT' peer. Routing IDs are transient.
|
||||
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
The _zmq_msg_routing_id()_ function shall return zero if there is no routing
|
||||
ID, otherwise it shall return an unsigned 32-bit integer greater than zero.
|
||||
|
||||
|
||||
EXAMPLE
|
||||
-------
|
||||
.Receiving a client message and routing ID
|
||||
----
|
||||
void *ctx = zmq_ctx_new ();
|
||||
assert (ctx);
|
||||
|
||||
void *server = zmq_socket (ctx, ZMQ_SERVER);
|
||||
assert (server);
|
||||
int rc = zmq_bind (server, "tcp://127.0.0.1:8080");
|
||||
assert (rc == 0);
|
||||
|
||||
zmq_msg_t message;
|
||||
rc = zmq_msg_init (&message);
|
||||
assert (rc == 0);
|
||||
|
||||
// Receive a message from socket
|
||||
rc = zmq_msg_recv (server, &message, 0);
|
||||
assert (rc != -1);
|
||||
uint32_t routing_id = zmq_msg_routing_id (&message);
|
||||
assert (routing_id);
|
||||
----
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkzmq:zmq_msg_set_routing_id[3]
|
||||
|
||||
|
||||
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>.
|
46
doc/zmq_msg_set_routing_id.txt
Normal file
46
doc/zmq_msg_set_routing_id.txt
Normal file
@ -0,0 +1,46 @@
|
||||
zmq_msg_set_routing_id(3)
|
||||
=========================
|
||||
|
||||
|
||||
NAME
|
||||
----
|
||||
|
||||
zmq_msg_set_routing_id - set routing ID property on message
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
*int zmq_msg_set_routing_id (zmq_msg_t '*message', uint32_t 'routing_id');*
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
The _zmq_msg_set_routing_id()_ function sets the 'routing_id' specified, on the
|
||||
the message pointed to by the 'message' argument. The 'routing_id' must be
|
||||
greater than zero. To get a valid routing ID, you must receive a message
|
||||
from a 'ZMQ_SERVER' socket, and use the libzmq:zmq_msg_routing_id method.
|
||||
Routing IDs are transient.
|
||||
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
The _zmq_msg_set_routing_id()_ function shall return zero if successful. Otherwise it
|
||||
shall return `-1` and set 'errno' to one of the values defined below.
|
||||
|
||||
|
||||
ERRORS
|
||||
------
|
||||
*EINVAL*::
|
||||
The provided 'routing_id' is zero.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkzmq:zmq_msg_routing_id[3]
|
||||
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>.
|
@ -48,7 +48,7 @@ _zmq_bind()_, thus allowing many-to-many relationships.
|
||||
|
||||
.Thread safety
|
||||
0MQ 'sockets' are _not_ thread safe. Applications MUST NOT use a socket
|
||||
from multiple threads except after migrating a socket from one thread to
|
||||
from multiple threads except after migrating a socket from one thread to
|
||||
another with a "full fence" memory barrier.
|
||||
|
||||
.Socket types
|
||||
@ -56,73 +56,45 @@ The following sections present the socket types defined by 0MQ, grouped by the
|
||||
general _messaging pattern_ which is built from related socket types.
|
||||
|
||||
|
||||
Request-reply pattern
|
||||
Client-server pattern
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
The request-reply pattern is used for sending requests from a ZMQ_REQ _client_
|
||||
to one or more ZMQ_REP _services_, and receiving subsequent replies to each
|
||||
request sent.
|
||||
|
||||
The request-reply pattern is formally defined by http://rfc.zeromq.org/spec:28.
|
||||
The client-server pattern is used to allow a single 'ZMQ_SERVER' _server_ talk
|
||||
to one or more 'ZMQ_CLIENT' _clients_. The client always starts the conversation,
|
||||
after which either peer can send messages asynchronously, to the other.
|
||||
|
||||
ZMQ_REQ
|
||||
^^^^^^^
|
||||
A socket of type 'ZMQ_REQ' is used by a _client_ to send requests to and
|
||||
receive replies from a _service_. This socket type allows only an alternating
|
||||
sequence of _zmq_send(request)_ and subsequent _zmq_recv(reply)_ calls. Each
|
||||
request sent is round-robined among all _services_, and each reply received is
|
||||
matched with the last issued request.
|
||||
The client-server pattern is formally defined by http://rfc.zeromq.org/spec:41.
|
||||
|
||||
If no services are available, then any send operation on the socket shall
|
||||
block until at least one _service_ becomes available. The REQ socket shall
|
||||
not discard messages.
|
||||
Note: this pattern deprecates the use of 'ZMQ_DEALER' and 'ZMQ_ROUTER' to build
|
||||
client-server architectures.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_REQ characteristics
|
||||
Compatible peer sockets:: 'ZMQ_REP', 'ZMQ_ROUTER'
|
||||
Direction:: Bidirectional
|
||||
Send/receive pattern:: Send, Receive, Send, Receive, ...
|
||||
Outgoing routing strategy:: Round-robin
|
||||
Incoming routing strategy:: Last peer
|
||||
Action in mute state:: Block
|
||||
|
||||
|
||||
ZMQ_REP
|
||||
^^^^^^^
|
||||
A socket of type 'ZMQ_REP' is used by a _service_ to receive requests from and
|
||||
send replies to a _client_. This socket type allows only an alternating
|
||||
sequence of _zmq_recv(request)_ and subsequent _zmq_send(reply)_ calls. Each
|
||||
request received is fair-queued from among all _clients_, and each reply sent
|
||||
is routed to the _client_ that issued the last request. If the original
|
||||
requester does not exist any more the reply is silently discarded.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_REP characteristics
|
||||
Compatible peer sockets:: 'ZMQ_REQ', 'ZMQ_DEALER'
|
||||
Direction:: Bidirectional
|
||||
Send/receive pattern:: Receive, Send, Receive, Send, ...
|
||||
Incoming routing strategy:: Fair-queued
|
||||
Outgoing routing strategy:: Last peer
|
||||
|
||||
|
||||
ZMQ_DEALER
|
||||
ZMQ_CLIENT
|
||||
^^^^^^^^^^
|
||||
A socket of type 'ZMQ_DEALER' is an advanced pattern used for extending
|
||||
request/reply sockets. Each message sent is round-robined among all connected
|
||||
peers, and each message received is fair-queued from all connected peers.
|
||||
A 'ZMQ_CLIENT' socket talks to a 'ZMQ_SERVER' socket. Either peer can connect,
|
||||
though the usual and recommended model is to bind the 'ZMQ_SERVER' and connect
|
||||
the 'ZMQ_CLIENT'.
|
||||
|
||||
When a 'ZMQ_DEALER' socket enters the 'mute' state due to having reached the
|
||||
high water mark for all peers, or if there are no peers at all, then any
|
||||
linkzmq:zmq_send[3] operations on the socket shall block until the mute
|
||||
state ends or at least one peer becomes available for sending; messages are not
|
||||
discarded.
|
||||
If the 'ZMQ_CLIENT' socket has established a connection, linkzmq:zmq_send[3]
|
||||
will accept messages, queue them, and send them as rapidly as the network
|
||||
allows. The outgoing buffer limit is defined by the high water mark for the
|
||||
socket. If the outgoing buffer is full, or if there is no connected peer,
|
||||
linkzmq:zmq_send[3] will block, by default. The 'ZMQ_CLIENT' socket will not
|
||||
drop messages.
|
||||
|
||||
When a 'ZMQ_DEALER' socket is connected to a 'ZMQ_REP' socket each message sent
|
||||
must consist of an empty message part, the _delimiter_, followed by one or more
|
||||
_body parts_.
|
||||
When a 'ZMQ_CLIENT' socket is connected to multiple 'ZMQ_SERVER' sockets,
|
||||
outgoing messages are distributed between connected peers on a round-robin
|
||||
basis. Likewise, the 'ZMQ_CLIENT' socket receives messages fairly from each
|
||||
connected peer. This usage is sensible only for stateless protocols.
|
||||
|
||||
'ZMQ_CLIENT' sockets are threadsafe and can be used from multiple threads
|
||||
at the same time. Note that replies from a 'ZMQ_SERVER' socket will go to
|
||||
the first client thread that calls libzmq:zmq_msg_recv. If you need to get
|
||||
replies back to the originating thread, use one 'ZMQ_CLIENT' socket per
|
||||
thread.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_DEALER characteristics
|
||||
Compatible peer sockets:: 'ZMQ_ROUTER', 'ZMQ_REP', 'ZMQ_DEALER'
|
||||
.Summary of ZMQ_CLIENT characteristics
|
||||
Compatible peer sockets:: 'ZMQ_SERVER'
|
||||
Direction:: Bidirectional
|
||||
Send/receive pattern:: Unrestricted
|
||||
Outgoing routing strategy:: Round-robin
|
||||
@ -130,38 +102,30 @@ Incoming routing strategy:: Fair-queued
|
||||
Action in mute state:: Block
|
||||
|
||||
|
||||
ZMQ_ROUTER
|
||||
ZMQ_SERVER
|
||||
^^^^^^^^^^
|
||||
A socket of type 'ZMQ_ROUTER' is an advanced socket type used for extending
|
||||
request/reply sockets. When receiving messages a 'ZMQ_ROUTER' socket shall
|
||||
prepend a message part containing the _identity_ of the originating peer to the
|
||||
message before passing it to the application. Messages received are fair-queued
|
||||
from among all connected peers. When sending messages a 'ZMQ_ROUTER' socket shall
|
||||
remove the first part of the message and use it to determine the _identity_ of
|
||||
the peer the message shall be routed to. If the peer does not exist anymore
|
||||
the message shall be silently discarded by default, unless 'ZMQ_ROUTER_MANDATORY'
|
||||
socket option is set to '1'.
|
||||
A 'ZMQ_SERVER' socket talks to a set of 'ZMQ_CLIENT' sockets. A 'ZMQ_SERVER'
|
||||
socket can only reply to an incoming message: the 'ZMQ_CLIENT' peer must
|
||||
always initiate a conversation.
|
||||
|
||||
When a 'ZMQ_ROUTER' socket enters the 'mute' state due to having reached the
|
||||
high water mark for all peers, then any messages sent to the socket shall be dropped
|
||||
until the mute state ends. Likewise, any messages routed to a peer for which
|
||||
the individual high water mark has been reached shall also be dropped.
|
||||
Each received message has a 'routing_id' that is a 32-bit unsigned integer.
|
||||
The application can fetch this with linkzmq:zmq_msg_routing_id[3]. To send
|
||||
a message to a given 'ZMQ_CLIENT' peer the application must set the peer's
|
||||
'routing_id' on the message, using linkzmq:zmq_msg_set_routing_id[3].
|
||||
|
||||
When a 'ZMQ_REQ' socket is connected to a 'ZMQ_ROUTER' socket, in addition to the
|
||||
_identity_ of the originating peer each message received shall contain an empty
|
||||
_delimiter_ message part. Hence, the entire structure of each received message
|
||||
as seen by the application becomes: one or more _identity_ parts, _delimiter_
|
||||
part, one or more _body parts_. When sending replies to a 'ZMQ_REQ' socket the
|
||||
application must include the _delimiter_ part.
|
||||
If the 'routing_id' is not specified, or does not refer to a connected client
|
||||
peer, the send call will fail with EHOSTUNREACH. If the outgoing buffer for
|
||||
the client peer is full, the send call will fail with EAGAIN. The 'ZMQ_SERVER'
|
||||
socket shall not drop messages, nor shall it block.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_ROUTER characteristics
|
||||
Compatible peer sockets:: 'ZMQ_DEALER', 'ZMQ_REQ', 'ZMQ_ROUTER'
|
||||
.Summary of ZMQ_SERVER characteristics
|
||||
Compatible peer sockets:: 'ZMQ_CLIENT'
|
||||
Direction:: Bidirectional
|
||||
Send/receive pattern:: Unrestricted
|
||||
Outgoing routing strategy:: See text
|
||||
Incoming routing strategy:: Fair-queued
|
||||
Action in mute state:: Drop
|
||||
Action in mute state:: Return EAGAIN
|
||||
|
||||
|
||||
Publish-subscribe pattern
|
||||
@ -328,26 +292,26 @@ Action in mute state:: Block
|
||||
|
||||
Native Pattern
|
||||
~~~~~~~~~~~~~~
|
||||
The native pattern is used for communicating with TCP peers and allows
|
||||
The native pattern is used for communicating with TCP peers and allows
|
||||
asynchronous requests and replies in either direction.
|
||||
|
||||
|
||||
ZMQ_STREAM
|
||||
^^^^^^^^^^
|
||||
A socket of type 'ZMQ_STREAM' is used to send and receive TCP data from a
|
||||
non-0MQ peer, when using the tcp:// transport. A 'ZMQ_STREAM' socket can
|
||||
A socket of type 'ZMQ_STREAM' is used to send and receive TCP data from a
|
||||
non-0MQ peer, when using the tcp:// transport. A 'ZMQ_STREAM' socket can
|
||||
act as client and/or server, sending and/or receiving TCP data asynchronously.
|
||||
|
||||
When receiving TCP data, a 'ZMQ_STREAM' socket shall prepend a message part
|
||||
containing the _identity_ of the originating peer to the message before passing
|
||||
it to the application. Messages received are fair-queued from among all
|
||||
connected peers.
|
||||
containing the _identity_ of the originating peer to the message before passing
|
||||
it to the application. Messages received are fair-queued from among all
|
||||
connected peers.
|
||||
|
||||
When sending TCP data, a 'ZMQ_STREAM' socket shall remove the first part of the
|
||||
message and use it to determine the _identity_ of the peer the message shall be
|
||||
When sending TCP data, a 'ZMQ_STREAM' socket shall remove the first part of the
|
||||
message and use it to determine the _identity_ of the peer the message shall be
|
||||
routed to, and unroutable messages shall cause an EHOSTUNREACH or EAGAIN error.
|
||||
|
||||
To open a connection to a server, use the zmq_connect call, and then fetch the
|
||||
To open a connection to a server, use the zmq_connect call, and then fetch the
|
||||
socket identity using the ZMQ_IDENTITY zmq_getsockopt call.
|
||||
|
||||
To close a specific connection, send the identity frame followed by a
|
||||
@ -373,6 +337,116 @@ Incoming routing strategy:: Fair-queued
|
||||
Action in mute state:: EAGAIN
|
||||
|
||||
|
||||
Request-reply pattern
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
The request-reply pattern is used for sending requests from a ZMQ_REQ _client_
|
||||
to one or more ZMQ_REP _services_, and receiving subsequent replies to each
|
||||
request sent.
|
||||
|
||||
The request-reply pattern is formally defined by http://rfc.zeromq.org/spec:28.
|
||||
|
||||
Note: this pattern will be deprecated in favor of the client-server pattern.
|
||||
|
||||
ZMQ_REQ
|
||||
^^^^^^^
|
||||
A socket of type 'ZMQ_REQ' is used by a _client_ to send requests to and
|
||||
receive replies from a _service_. This socket type allows only an alternating
|
||||
sequence of _zmq_send(request)_ and subsequent _zmq_recv(reply)_ calls. Each
|
||||
request sent is round-robined among all _services_, and each reply received is
|
||||
matched with the last issued request.
|
||||
|
||||
If no services are available, then any send operation on the socket shall
|
||||
block until at least one _service_ becomes available. The REQ socket shall
|
||||
not discard messages.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_REQ characteristics
|
||||
Compatible peer sockets:: 'ZMQ_REP', 'ZMQ_ROUTER'
|
||||
Direction:: Bidirectional
|
||||
Send/receive pattern:: Send, Receive, Send, Receive, ...
|
||||
Outgoing routing strategy:: Round-robin
|
||||
Incoming routing strategy:: Last peer
|
||||
Action in mute state:: Block
|
||||
|
||||
|
||||
ZMQ_REP
|
||||
^^^^^^^
|
||||
A socket of type 'ZMQ_REP' is used by a _service_ to receive requests from and
|
||||
send replies to a _client_. This socket type allows only an alternating
|
||||
sequence of _zmq_recv(request)_ and subsequent _zmq_send(reply)_ calls. Each
|
||||
request received is fair-queued from among all _clients_, and each reply sent
|
||||
is routed to the _client_ that issued the last request. If the original
|
||||
requester does not exist any more the reply is silently discarded.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_REP characteristics
|
||||
Compatible peer sockets:: 'ZMQ_REQ', 'ZMQ_DEALER'
|
||||
Direction:: Bidirectional
|
||||
Send/receive pattern:: Receive, Send, Receive, Send, ...
|
||||
Incoming routing strategy:: Fair-queued
|
||||
Outgoing routing strategy:: Last peer
|
||||
|
||||
|
||||
ZMQ_DEALER
|
||||
^^^^^^^^^^
|
||||
A socket of type 'ZMQ_DEALER' is an advanced pattern used for extending
|
||||
request/reply sockets. Each message sent is round-robined among all connected
|
||||
peers, and each message received is fair-queued from all connected peers.
|
||||
|
||||
When a 'ZMQ_DEALER' socket enters the 'mute' state due to having reached the
|
||||
high water mark for all peers, or if there are no peers at all, then any
|
||||
linkzmq:zmq_send[3] operations on the socket shall block until the mute
|
||||
state ends or at least one peer becomes available for sending; messages are not
|
||||
discarded.
|
||||
|
||||
When a 'ZMQ_DEALER' socket is connected to a 'ZMQ_REP' socket each message sent
|
||||
must consist of an empty message part, the _delimiter_, followed by one or more
|
||||
_body parts_.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_DEALER characteristics
|
||||
Compatible peer sockets:: 'ZMQ_ROUTER', 'ZMQ_REP', 'ZMQ_DEALER'
|
||||
Direction:: Bidirectional
|
||||
Send/receive pattern:: Unrestricted
|
||||
Outgoing routing strategy:: Round-robin
|
||||
Incoming routing strategy:: Fair-queued
|
||||
Action in mute state:: Block
|
||||
|
||||
|
||||
ZMQ_ROUTER
|
||||
^^^^^^^^^^
|
||||
A socket of type 'ZMQ_ROUTER' is an advanced socket type used for extending
|
||||
request/reply sockets. When receiving messages a 'ZMQ_ROUTER' socket shall
|
||||
prepend a message part containing the _identity_ of the originating peer to the
|
||||
message before passing it to the application. Messages received are fair-queued
|
||||
from among all connected peers. When sending messages a 'ZMQ_ROUTER' socket shall
|
||||
remove the first part of the message and use it to determine the _identity_ of
|
||||
the peer the message shall be routed to. If the peer does not exist anymore
|
||||
the message shall be silently discarded by default, unless 'ZMQ_ROUTER_MANDATORY'
|
||||
socket option is set to '1'.
|
||||
|
||||
When a 'ZMQ_ROUTER' socket enters the 'mute' state due to having reached the
|
||||
high water mark for all peers, then any messages sent to the socket shall be dropped
|
||||
until the mute state ends. Likewise, any messages routed to a peer for which
|
||||
the individual high water mark has been reached shall also be dropped.
|
||||
|
||||
When a 'ZMQ_REQ' socket is connected to a 'ZMQ_ROUTER' socket, in addition to the
|
||||
_identity_ of the originating peer each message received shall contain an empty
|
||||
_delimiter_ message part. Hence, the entire structure of each received message
|
||||
as seen by the application becomes: one or more _identity_ parts, _delimiter_
|
||||
part, one or more _body parts_. When sending replies to a 'ZMQ_REQ' socket the
|
||||
application must include the _delimiter_ part.
|
||||
|
||||
[horizontal]
|
||||
.Summary of ZMQ_ROUTER characteristics
|
||||
Compatible peer sockets:: 'ZMQ_DEALER', 'ZMQ_REQ', 'ZMQ_ROUTER'
|
||||
Direction:: Bidirectional
|
||||
Send/receive pattern:: Unrestricted
|
||||
Outgoing routing strategy:: See text
|
||||
Incoming routing strategy:: Fair-queued
|
||||
Action in mute state:: Drop
|
||||
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
The _zmq_socket()_ function shall return an opaque handle to the newly created
|
||||
|
@ -227,8 +227,8 @@ ZMQ_EXPORT int zmq_msg_more (zmq_msg_t *msg);
|
||||
ZMQ_EXPORT int zmq_msg_get (zmq_msg_t *msg, int property);
|
||||
ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg, int property, int optval);
|
||||
ZMQ_EXPORT const char *zmq_msg_gets (zmq_msg_t *msg, const char *property);
|
||||
ZMQ_EXPORT int zmq_msg_set_routing_id(zmq_msg_t *msg, uint32_t routing_id);
|
||||
ZMQ_EXPORT uint32_t zmq_msg_get_routing_id(zmq_msg_t *msg);
|
||||
ZMQ_EXPORT int zmq_msg_set_routing_id (zmq_msg_t *msg, uint32_t routing_id);
|
||||
ZMQ_EXPORT uint32_t zmq_msg_routing_id (zmq_msg_t *msg);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -44,9 +44,9 @@ zmq::client_t::~client_t ()
|
||||
|
||||
void zmq::client_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
||||
{
|
||||
LIBZMQ_UNUSED(subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
zmq_assert (pipe_);
|
||||
|
||||
fq.attach (pipe_);
|
||||
lb.attach (pipe_);
|
||||
@ -54,28 +54,26 @@ void zmq::client_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
||||
|
||||
int zmq::client_t::xsend (msg_t *msg_)
|
||||
{
|
||||
zmq_assert(!(msg_->flags () & msg_t::more));
|
||||
|
||||
return lb.sendpipe (msg_, NULL);
|
||||
}
|
||||
|
||||
int zmq::client_t::xrecv (msg_t *msg_)
|
||||
{
|
||||
{
|
||||
int rc = fq.recvpipe (msg_, NULL);
|
||||
|
||||
// Drop any messages with more flag
|
||||
while (rc == 0 && msg_->flags () & msg_t::more) {
|
||||
|
||||
// drop all frames of the current multi-frame message
|
||||
rc = fq.recvpipe (msg_, NULL);
|
||||
|
||||
rc = fq.recvpipe (msg_, NULL);
|
||||
|
||||
while (rc == 0 && msg_->flags () & msg_t::more)
|
||||
rc = fq.recvpipe (msg_, NULL);
|
||||
rc = fq.recvpipe (msg_, NULL);
|
||||
|
||||
// get the new message
|
||||
if (rc == 0)
|
||||
if (rc == 0)
|
||||
rc = fq.recvpipe (msg_, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ zmq::dealer_t::~dealer_t ()
|
||||
|
||||
void zmq::dealer_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
||||
{
|
||||
LIBZMQ_UNUSED(subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
|
||||
|
@ -74,7 +74,8 @@ const char *zmq::mechanism_t::socket_type_string (int socket_type) const
|
||||
{
|
||||
static const char *names [] = {"PAIR", "PUB", "SUB", "REQ", "REP",
|
||||
"DEALER", "ROUTER", "PULL", "PUSH",
|
||||
"XPUB", "XSUB", "STREAM", "SERVER", "CLIENT"};
|
||||
"XPUB", "XSUB", "STREAM",
|
||||
"SERVER", "CLIENT"};
|
||||
zmq_assert (socket_type >= 0 && socket_type <= 13);
|
||||
return names [socket_type];
|
||||
}
|
||||
@ -190,7 +191,7 @@ bool zmq::mechanism_t::check_socket_type (const std::string& type_) const
|
||||
case ZMQ_SERVER:
|
||||
return type_ == "CLIENT";
|
||||
case ZMQ_CLIENT:
|
||||
return type_ == "CLIENT" || type_ == "SERVER";
|
||||
return type_ == "SERVER";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
14
src/msg.cpp
14
src/msg.cpp
@ -497,18 +497,22 @@ bool zmq::msg_t::rm_refs (int refs_)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t zmq::msg_t::get_routing_id()
|
||||
uint32_t zmq::msg_t::get_routing_id ()
|
||||
{
|
||||
return u.base.routing_id;
|
||||
}
|
||||
|
||||
int zmq::msg_t::set_routing_id(uint32_t routing_id_)
|
||||
int zmq::msg_t::set_routing_id (uint32_t routing_id_)
|
||||
{
|
||||
u.base.routing_id = routing_id_;
|
||||
return 0;
|
||||
if (routing_id_) {
|
||||
u.base.routing_id = routing_id_;
|
||||
return 0;
|
||||
}
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
zmq::atomic_counter_t* zmq::msg_t::refcnt()
|
||||
zmq::atomic_counter_t *zmq::msg_t::refcnt()
|
||||
{
|
||||
switch(u.base.type)
|
||||
{
|
||||
|
@ -97,8 +97,8 @@ namespace zmq
|
||||
bool is_vsm () const;
|
||||
bool is_cmsg () const;
|
||||
bool is_zcmsg() const;
|
||||
uint32_t get_routing_id();
|
||||
int set_routing_id(uint32_t routing_id_);
|
||||
uint32_t get_routing_id ();
|
||||
int set_routing_id (uint32_t routing_id_);
|
||||
|
||||
// After calling this function you can copy the message in POD-style
|
||||
// refs_ times. No need to call copy.
|
||||
|
@ -48,7 +48,7 @@ zmq::pair_t::~pair_t ()
|
||||
|
||||
void zmq::pair_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
||||
{
|
||||
LIBZMQ_UNUSED(subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
|
||||
zmq_assert (pipe_ != NULL);
|
||||
|
||||
|
@ -85,8 +85,8 @@ namespace zmq
|
||||
void set_event_sink (i_pipe_events *sink_);
|
||||
|
||||
// Pipe endpoint can store an routing ID to be used by its clients.
|
||||
void set_routing_id(uint32_t routing_id_);
|
||||
uint32_t get_routing_id();
|
||||
void set_routing_id (uint32_t routing_id_);
|
||||
uint32_t get_routing_id ();
|
||||
|
||||
// Pipe endpoint can store an opaque ID to be used by its clients.
|
||||
void set_identity (const blob_t &identity_);
|
||||
|
@ -45,7 +45,7 @@ zmq::pull_t::~pull_t ()
|
||||
|
||||
void zmq::pull_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
||||
{
|
||||
LIBZMQ_UNUSED(subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
fq.attach (pipe_);
|
||||
|
@ -45,7 +45,7 @@ zmq::push_t::~push_t ()
|
||||
|
||||
void zmq::push_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
||||
{
|
||||
LIBZMQ_UNUSED(subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
|
||||
// Don't delay pipe termination as there is no one
|
||||
// to receive the delimiter.
|
||||
|
@ -45,7 +45,7 @@ zmq::router_t::router_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
|
||||
next_rid (generate_random ()),
|
||||
mandatory (false),
|
||||
// raw_socket functionality in ROUTER is deprecated
|
||||
raw_socket (false),
|
||||
raw_socket (false),
|
||||
probe_router (false),
|
||||
handover (false)
|
||||
{
|
||||
@ -67,7 +67,7 @@ zmq::router_t::~router_t ()
|
||||
|
||||
void zmq::router_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
||||
{
|
||||
LIBZMQ_UNUSED(subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
|
||||
@ -104,6 +104,7 @@ int zmq::router_t::xsetsockopt (int option_, const void *optval_,
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_ROUTER_RAW:
|
||||
if (is_int && value >= 0) {
|
||||
raw_socket = (value != 0);
|
||||
@ -128,8 +129,8 @@ int zmq::router_t::xsetsockopt (int option_, const void *optval_,
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_ROUTER_HANDOVER:
|
||||
|
||||
case ZMQ_ROUTER_HANDOVER:
|
||||
if (is_int && value >= 0) {
|
||||
handover = (value != 0);
|
||||
return 0;
|
||||
@ -409,10 +410,10 @@ bool zmq::router_t::identify_peer (pipe_t *pipe_)
|
||||
connect_rid.length());
|
||||
connect_rid.clear ();
|
||||
outpipes_t::iterator it = outpipes.find (identity);
|
||||
if (it != outpipes.end ())
|
||||
if (it != outpipes.end ())
|
||||
zmq_assert(false); // Not allowed to duplicate an existing rid
|
||||
}
|
||||
else
|
||||
else
|
||||
if (options.raw_socket) { // Always assign identity for raw-socket
|
||||
unsigned char buf [5];
|
||||
buf [0] = 0;
|
||||
@ -420,7 +421,7 @@ bool zmq::router_t::identify_peer (pipe_t *pipe_)
|
||||
identity = blob_t (buf, sizeof buf);
|
||||
}
|
||||
else
|
||||
if (!options.raw_socket) {
|
||||
if (!options.raw_socket) {
|
||||
// Pick up handshake cases and also case where next identity is set
|
||||
msg.init ();
|
||||
ok = pipe_->read (&msg);
|
||||
@ -446,7 +447,7 @@ bool zmq::router_t::identify_peer (pipe_t *pipe_)
|
||||
return false;
|
||||
else {
|
||||
// We will allow the new connection to take over this
|
||||
// identity. Temporarily assign a new identity to the
|
||||
// identity. Temporarily assign a new identity to the
|
||||
// existing pipe so we can terminate it asynchronously.
|
||||
unsigned char buf [5];
|
||||
buf [0] = 0;
|
||||
@ -454,13 +455,13 @@ bool zmq::router_t::identify_peer (pipe_t *pipe_)
|
||||
blob_t new_identity = blob_t (buf, sizeof buf);
|
||||
|
||||
it->second.pipe->set_identity (new_identity);
|
||||
outpipe_t existing_outpipe =
|
||||
outpipe_t existing_outpipe =
|
||||
{it->second.pipe, it->second.active};
|
||||
|
||||
|
||||
ok = outpipes.insert (outpipes_t::value_type (
|
||||
new_identity, existing_outpipe)).second;
|
||||
zmq_assert (ok);
|
||||
|
||||
|
||||
// Remove the existing identity entry to allow the new
|
||||
// connection to take the identity.
|
||||
outpipes.erase (it);
|
||||
|
@ -39,28 +39,31 @@ zmq::server_t::server_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
|
||||
socket_base_t (parent_, tid_, sid_, true),
|
||||
next_rid (generate_random ())
|
||||
{
|
||||
options.type = ZMQ_SERVER;
|
||||
options.type = ZMQ_SERVER;
|
||||
}
|
||||
|
||||
zmq::server_t::~server_t ()
|
||||
{
|
||||
{
|
||||
zmq_assert (outpipes.empty ());
|
||||
}
|
||||
|
||||
void zmq::server_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
||||
{
|
||||
LIBZMQ_UNUSED(subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
zmq_assert (pipe_);
|
||||
|
||||
uint32_t routing_id = next_rid++;
|
||||
if (!routing_id)
|
||||
routing_id = next_rid++; // Never use RID zero
|
||||
|
||||
pipe_->set_routing_id (routing_id);
|
||||
// Add the record into output pipes lookup table
|
||||
outpipe_t outpipe = {pipe_, true};
|
||||
bool ok = outpipes.insert (outpipes_t::value_type (routing_id, outpipe)).second;
|
||||
zmq_assert (ok);
|
||||
|
||||
fq.attach (pipe_);
|
||||
|
||||
fq.attach (pipe_);
|
||||
}
|
||||
|
||||
void zmq::server_t::xpipe_terminated (pipe_t *pipe_)
|
||||
@ -68,12 +71,12 @@ void zmq::server_t::xpipe_terminated (pipe_t *pipe_)
|
||||
outpipes_t::iterator it = outpipes.find (pipe_->get_routing_id ());
|
||||
zmq_assert (it != outpipes.end ());
|
||||
outpipes.erase (it);
|
||||
fq.pipe_terminated (pipe_);
|
||||
fq.pipe_terminated (pipe_);
|
||||
}
|
||||
|
||||
void zmq::server_t::xread_activated (pipe_t *pipe_)
|
||||
{
|
||||
fq.activated (pipe_);
|
||||
{
|
||||
fq.activated (pipe_);
|
||||
}
|
||||
|
||||
void zmq::server_t::xwrite_activated (pipe_t *pipe_)
|
||||
@ -90,20 +93,18 @@ void zmq::server_t::xwrite_activated (pipe_t *pipe_)
|
||||
|
||||
int zmq::server_t::xsend (msg_t *msg_)
|
||||
{
|
||||
zmq_assert(!(msg_->flags () & msg_t::more));
|
||||
|
||||
// Find the pipe associated with the routing stored in the message.
|
||||
uint32_t routing_id = msg_->get_routing_id();
|
||||
// Find the pipe associated with the routing stored in the message.
|
||||
uint32_t routing_id = msg_->get_routing_id ();
|
||||
outpipes_t::iterator it = outpipes.find (routing_id);
|
||||
|
||||
if (it != outpipes.end ()) {
|
||||
|
||||
if (it != outpipes.end ()) {
|
||||
if (!it->second.pipe->check_write ()) {
|
||||
it->second.active = false;
|
||||
it->second.active = false;
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else {
|
||||
errno = EHOSTUNREACH;
|
||||
return -1;
|
||||
}
|
||||
@ -113,10 +114,11 @@ int zmq::server_t::xsend (msg_t *msg_)
|
||||
// Message failed to send - we must close it ourselves.
|
||||
int rc = msg_->close ();
|
||||
errno_assert (rc == 0);
|
||||
} else {
|
||||
it->second.pipe->flush ();
|
||||
}
|
||||
|
||||
else
|
||||
it->second.pipe->flush ();
|
||||
|
||||
|
||||
// Detach the message from the data buffer.
|
||||
int rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
@ -125,7 +127,7 @@ int zmq::server_t::xsend (msg_t *msg_)
|
||||
}
|
||||
|
||||
int zmq::server_t::xrecv (msg_t *msg_)
|
||||
{
|
||||
{
|
||||
pipe_t *pipe = NULL;
|
||||
int rc = fq.recvpipe (msg_, &pipe);
|
||||
|
||||
@ -134,22 +136,22 @@ int zmq::server_t::xrecv (msg_t *msg_)
|
||||
|
||||
// drop all frames of the current multi-frame message
|
||||
rc = fq.recvpipe (msg_, NULL);
|
||||
|
||||
|
||||
while (rc == 0 && msg_->flags () & msg_t::more)
|
||||
rc = fq.recvpipe (msg_, NULL);
|
||||
rc = fq.recvpipe (msg_, NULL);
|
||||
|
||||
// get the new message
|
||||
if (rc == 0)
|
||||
if (rc == 0)
|
||||
rc = fq.recvpipe (msg_, &pipe);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
return rc;
|
||||
|
||||
zmq_assert (pipe != NULL);
|
||||
|
||||
uint32_t routing_id = pipe->get_routing_id();
|
||||
msg_->set_routing_id(routing_id);
|
||||
uint32_t routing_id = pipe->get_routing_id ();
|
||||
msg_->set_routing_id (routing_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
10
src/tcp.cpp
10
src/tcp.cpp
@ -95,13 +95,13 @@ void zmq::set_tcp_receive_buffer (fd_t sockfd_, int bufsize_)
|
||||
void zmq::tune_tcp_keepalives (fd_t s_, int keepalive_, int keepalive_cnt_, int keepalive_idle_, int keepalive_intvl_)
|
||||
{
|
||||
// These options are used only under certain #ifdefs below.
|
||||
LIBZMQ_UNUSED(keepalive_);
|
||||
LIBZMQ_UNUSED(keepalive_cnt_);
|
||||
LIBZMQ_UNUSED(keepalive_idle_);
|
||||
LIBZMQ_UNUSED(keepalive_intvl_);
|
||||
LIBZMQ_UNUSED (keepalive_);
|
||||
LIBZMQ_UNUSED (keepalive_cnt_);
|
||||
LIBZMQ_UNUSED (keepalive_idle_);
|
||||
LIBZMQ_UNUSED (keepalive_intvl_);
|
||||
|
||||
// If none of the #ifdefs apply, then s_ is unused.
|
||||
LIBZMQ_UNUSED(s_);
|
||||
LIBZMQ_UNUSED (s_);
|
||||
|
||||
// Tuning TCP keep-alives if platform allows it
|
||||
// All values = -1 means skip and leave it for OS
|
||||
|
@ -57,7 +57,7 @@
|
||||
int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_, bool is_src_)
|
||||
{
|
||||
// TODO: Unused parameter, IPv6 support not implemented for Solaris.
|
||||
LIBZMQ_UNUSED(ipv6_);
|
||||
LIBZMQ_UNUSED (ipv6_);
|
||||
|
||||
// Create a socket.
|
||||
const int fd = open_socket (AF_INET, SOCK_DGRAM, 0);
|
||||
@ -124,7 +124,7 @@ int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_, bool is_
|
||||
int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_, bool is_src_)
|
||||
{
|
||||
// TODO: Unused parameter, IPv6 support not implemented for AIX or HP/UX.
|
||||
LIBZMQ_UNUSED(ipv6_);
|
||||
LIBZMQ_UNUSED (ipv6_);
|
||||
|
||||
// Create a socket.
|
||||
const int sd = open_socket (AF_INET, SOCK_DGRAM, 0);
|
||||
@ -211,8 +211,8 @@ int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_, bool is_
|
||||
// This is true especially of Windows.
|
||||
int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_, bool is_src_)
|
||||
{
|
||||
LIBZMQ_UNUSED(nic_);
|
||||
LIBZMQ_UNUSED(ipv6_);
|
||||
LIBZMQ_UNUSED (nic_);
|
||||
LIBZMQ_UNUSED (ipv6_);
|
||||
|
||||
errno = ENODEV;
|
||||
return -1;
|
||||
|
@ -56,7 +56,7 @@ zmq::xsub_t::~xsub_t ()
|
||||
|
||||
void zmq::xsub_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
|
||||
{
|
||||
LIBZMQ_UNUSED(subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
fq.attach (pipe_);
|
||||
|
@ -686,19 +686,19 @@ int zmq_msg_set (zmq_msg_t *, int, int)
|
||||
|
||||
int zmq_msg_set_routing_id (zmq_msg_t *msg_, uint32_t routing_id_)
|
||||
{
|
||||
return ((zmq::msg_t*) msg_)->set_routing_id(routing_id_);
|
||||
return ((zmq::msg_t *) msg_)->set_routing_id (routing_id_);
|
||||
}
|
||||
|
||||
uint32_t zmq_msg_get_routing_id(zmq_msg_t *msg_)
|
||||
uint32_t zmq_msg_routing_id (zmq_msg_t *msg_)
|
||||
{
|
||||
return ((zmq::msg_t*) msg_)->get_routing_id();
|
||||
return ((zmq::msg_t *) msg_)->get_routing_id ();
|
||||
}
|
||||
|
||||
// Get message metadata string
|
||||
|
||||
const char *zmq_msg_gets (zmq_msg_t *msg_, const char *property_)
|
||||
{
|
||||
zmq::metadata_t *metadata = ((zmq::msg_t*) msg_)->metadata ();
|
||||
zmq::metadata_t *metadata = ((zmq::msg_t *) msg_)->metadata ();
|
||||
const char *value = NULL;
|
||||
if (metadata)
|
||||
value = metadata->get (std::string (property_));
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
#include "testutil.hpp"
|
||||
|
||||
int send_msg(zmq_msg_t* msg, void* s, int flags, int value);
|
||||
int send_msg (zmq_msg_t* msg, void* s, int flags, int value);
|
||||
|
||||
int main (void)
|
||||
{
|
||||
@ -38,14 +38,14 @@ int main (void)
|
||||
assert (ctx);
|
||||
|
||||
void *client = zmq_socket (ctx, ZMQ_CLIENT);
|
||||
void *dealer = zmq_socket (ctx, ZMQ_DEALER);
|
||||
void *server = zmq_socket (ctx, ZMQ_SERVER);
|
||||
|
||||
int rc;
|
||||
|
||||
rc = zmq_bind (client, "inproc://serverdropmore");
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_connect (dealer, "inproc://serverdropmore");
|
||||
rc = zmq_connect (server, "inproc://serverdropmore");
|
||||
assert (rc == 0);
|
||||
|
||||
zmq_msg_t msg;
|
||||
@ -53,34 +53,34 @@ int main (void)
|
||||
assert (rc == 0);
|
||||
|
||||
// we will send 2 3-frames messages and then single frame message, only last one should be received
|
||||
rc = send_msg (&msg, dealer, ZMQ_SNDMORE, 1);
|
||||
rc = send_msg (&msg, client, ZMQ_SNDMORE, 1);
|
||||
assert(rc == 1);
|
||||
|
||||
rc = send_msg (&msg, dealer, ZMQ_SNDMORE, 2);
|
||||
rc = send_msg (&msg, client, ZMQ_SNDMORE, 2);
|
||||
assert(rc == 1);
|
||||
|
||||
rc = send_msg (&msg, dealer, 0, 3);
|
||||
assert(rc == 1);
|
||||
|
||||
rc = send_msg (&msg, dealer, ZMQ_SNDMORE, 4);
|
||||
rc = send_msg (&msg, client, 0, 3);
|
||||
assert(rc == 1);
|
||||
|
||||
rc = send_msg (&msg, dealer, ZMQ_SNDMORE, 5);
|
||||
assert(rc == 1);
|
||||
|
||||
rc = send_msg (&msg, dealer, 0, 6);
|
||||
rc = send_msg (&msg, client, ZMQ_SNDMORE, 4);
|
||||
assert(rc == 1);
|
||||
|
||||
rc = send_msg (&msg, dealer, 0, 7);
|
||||
rc = send_msg (&msg, client, ZMQ_SNDMORE, 5);
|
||||
assert(rc == 1);
|
||||
|
||||
rc = zmq_msg_recv (&msg, client, 0);
|
||||
assert (rc == 1);
|
||||
rc = send_msg (&msg, client, 0, 6);
|
||||
assert(rc == 1);
|
||||
|
||||
assert(zmq_msg_more(&msg) == 0);
|
||||
rc = send_msg (&msg, client, 0, 7);
|
||||
assert(rc == 1);
|
||||
|
||||
unsigned char* data = (unsigned char*)zmq_msg_data (&msg);
|
||||
assert (data[0] == 7);
|
||||
rc = zmq_msg_recv (&msg, server, 0);
|
||||
assert (rc == 1);
|
||||
|
||||
assert (zmq_msg_more (&msg) == 0);
|
||||
|
||||
unsigned char *data = (unsigned char*) zmq_msg_data (&msg);
|
||||
assert (data [0] == 7);
|
||||
|
||||
rc = zmq_msg_close (&msg);
|
||||
assert (rc == 0);
|
||||
@ -88,7 +88,7 @@ int main (void)
|
||||
rc = zmq_close (client);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_close (dealer);
|
||||
rc = zmq_close (server);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_ctx_term (ctx);
|
||||
@ -97,20 +97,18 @@ int main (void)
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
int send_msg(zmq_msg_t* msg, void* s, int flags, int value)
|
||||
int send_msg (zmq_msg_t *msg, void *s, int flags, int value)
|
||||
{
|
||||
int rc = zmq_msg_close(msg);
|
||||
|
||||
int rc = zmq_msg_close (msg);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
zmq_msg_init_size(msg, 1);
|
||||
|
||||
zmq_msg_init_size (msg, 1);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
unsigned char* data = (unsigned char*)zmq_msg_data(msg);
|
||||
data[0] = (unsigned char)value;
|
||||
unsigned char *data = (unsigned char *) zmq_msg_data (msg);
|
||||
data [0] = (unsigned char) value;
|
||||
|
||||
return zmq_msg_send (msg, s, flags);
|
||||
}
|
||||
|
@ -38,31 +38,29 @@ int main (void)
|
||||
void *server = zmq_socket (ctx, ZMQ_SERVER);
|
||||
void *client = zmq_socket (ctx, ZMQ_CLIENT);
|
||||
|
||||
int rc;
|
||||
|
||||
rc = zmq_bind (server, "tcp://127.0.0.1:5560");
|
||||
int rc = zmq_bind (server, "tcp://127.0.0.1:5560");
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_connect (client, "tcp://127.0.0.1:5560");
|
||||
assert (rc == 0);
|
||||
|
||||
zmq_msg_t msg;
|
||||
rc = zmq_msg_init_size(&msg,1);
|
||||
rc = zmq_msg_init_size (&msg, 1);
|
||||
assert (rc == 0);
|
||||
|
||||
char * data = (char *)zmq_msg_data(&msg);
|
||||
data[0] = 1;
|
||||
char *data = (char *) zmq_msg_data (&msg);
|
||||
data [0] = 1;
|
||||
|
||||
rc = zmq_msg_send(&msg, client, 0);
|
||||
assert (rc == 1);
|
||||
|
||||
rc = zmq_msg_init(&msg);
|
||||
rc = zmq_msg_init (&msg);
|
||||
assert (rc == 0);
|
||||
rc = zmq_msg_recv(&msg, server, 0);
|
||||
rc = zmq_msg_recv (&msg, server, 0);
|
||||
assert (rc == 1);
|
||||
|
||||
uint32_t routing_id = zmq_msg_get_routing_id(&msg);
|
||||
assert(routing_id != 0);
|
||||
uint32_t routing_id = zmq_msg_routing_id (&msg);
|
||||
assert (routing_id != 0);
|
||||
|
||||
rc = zmq_msg_close(&msg);
|
||||
assert (rc == 0);
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
#include "testutil.hpp"
|
||||
|
||||
int send_msg(zmq_msg_t* msg, void* s, int flags, int value);
|
||||
int send_msg (zmq_msg_t* msg, void* s, int flags, int value);
|
||||
|
||||
int main (void)
|
||||
{
|
||||
@ -38,7 +38,7 @@ int main (void)
|
||||
assert (ctx);
|
||||
|
||||
void *server = zmq_socket (ctx, ZMQ_SERVER);
|
||||
void *client = zmq_socket (ctx, ZMQ_DEALER);
|
||||
void *client = zmq_socket (ctx, ZMQ_CLIENT);
|
||||
|
||||
int rc;
|
||||
|
||||
@ -61,13 +61,13 @@ int main (void)
|
||||
|
||||
rc = send_msg (&msg, client, 0, 3);
|
||||
assert(rc == 1);
|
||||
|
||||
|
||||
rc = send_msg (&msg, client, ZMQ_SNDMORE, 4);
|
||||
assert(rc == 1);
|
||||
|
||||
rc = send_msg (&msg, client, ZMQ_SNDMORE, 5);
|
||||
assert(rc == 1);
|
||||
|
||||
|
||||
rc = send_msg (&msg, client, 0, 6);
|
||||
assert(rc == 1);
|
||||
|
||||
@ -75,12 +75,12 @@ int main (void)
|
||||
assert(rc == 1);
|
||||
|
||||
rc = zmq_msg_recv (&msg, server, 0);
|
||||
assert (rc == 1);
|
||||
assert (rc == 1);
|
||||
|
||||
assert(zmq_msg_more(&msg) == 0);
|
||||
assert (zmq_msg_more (&msg) == 0);
|
||||
|
||||
unsigned char* data = (unsigned char*)zmq_msg_data (&msg);
|
||||
assert (data[0] == 7);
|
||||
unsigned char *data = (unsigned char*) zmq_msg_data (&msg);
|
||||
assert (data [0] == 7);
|
||||
|
||||
rc = zmq_msg_close (&msg);
|
||||
assert (rc == 0);
|
||||
@ -97,20 +97,18 @@ int main (void)
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
int send_msg(zmq_msg_t* msg, void* s, int flags, int value)
|
||||
int send_msg (zmq_msg_t *msg, void *s, int flags, int value)
|
||||
{
|
||||
int rc = zmq_msg_close(msg);
|
||||
|
||||
int rc = zmq_msg_close (msg);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
zmq_msg_init_size(msg, 1);
|
||||
|
||||
zmq_msg_init_size (msg, 1);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
unsigned char* data = (unsigned char*)zmq_msg_data(msg);
|
||||
data[0] = (unsigned char)value;
|
||||
unsigned char *data = (unsigned char *) zmq_msg_data (msg);
|
||||
data [0] = (unsigned char) value;
|
||||
|
||||
return zmq_msg_send (msg, s, flags);
|
||||
}
|
||||
|
@ -29,71 +29,51 @@
|
||||
|
||||
#include "testutil.hpp"
|
||||
|
||||
void worker1(void* s);
|
||||
void worker2(void* s);
|
||||
// Client threads loop on send/recv until told to exit
|
||||
void client_thread (void *client)
|
||||
{
|
||||
char data = 0;
|
||||
for (int count = 0; count < 100000; count++) {
|
||||
int rc = zmq_send (client, &data, 1, 0);
|
||||
assert (rc == 1);
|
||||
}
|
||||
data = 1;
|
||||
int rc = zmq_send (client, &data, 1, 0);
|
||||
assert (rc == 1);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
setup_test_environment();
|
||||
setup_test_environment ();
|
||||
void *ctx = zmq_ctx_new ();
|
||||
assert (ctx);
|
||||
|
||||
void *server = zmq_socket (ctx, ZMQ_SERVER);
|
||||
int rc = zmq_bind (server, "tcp://127.0.0.1:5560");
|
||||
assert (rc == 0);
|
||||
|
||||
void *client = zmq_socket (ctx, ZMQ_CLIENT);
|
||||
void *client2 = zmq_socket (ctx, ZMQ_CLIENT);
|
||||
|
||||
int thread_safe;
|
||||
size_t size = sizeof(int);
|
||||
|
||||
size_t size = sizeof (int);
|
||||
zmq_getsockopt (client, ZMQ_THREAD_SAFE, &thread_safe, &size);
|
||||
|
||||
assert (thread_safe == 1);
|
||||
|
||||
int rc;
|
||||
|
||||
rc = zmq_bind (client, "tcp://127.0.0.1:5560");
|
||||
rc = zmq_connect (client, "tcp://127.0.0.1:5560");
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_connect (client2, "tcp://127.0.0.1:5560");
|
||||
assert (rc == 0);
|
||||
void *t1 = zmq_threadstart (client_thread, client);
|
||||
void *t2 = zmq_threadstart (client_thread, client);
|
||||
|
||||
void* t1 = zmq_threadstart(worker1, client2);
|
||||
void* t2 = zmq_threadstart(worker2, client2);
|
||||
|
||||
char data[1];
|
||||
data[0] = 0;
|
||||
|
||||
for (int i=0; i < 10; i++) {
|
||||
rc = zmq_send_const(client, data, 1, 0);
|
||||
assert (rc == 1);
|
||||
|
||||
rc = zmq_send_const(client, data, 1, 0);
|
||||
assert(rc == 1);
|
||||
|
||||
char a, b;
|
||||
|
||||
rc = zmq_recv(client, &a, 1, 0);
|
||||
assert(rc == 1);
|
||||
|
||||
rc = zmq_recv(client, &b, 1, 0);
|
||||
assert(rc == 1);
|
||||
|
||||
// make sure they came from different threads
|
||||
assert((a == 1 && b == 2) || (a == 2 && b == 1));
|
||||
char data;
|
||||
int threads_completed = 0;
|
||||
while (threads_completed < 2) {
|
||||
zmq_recv (server, &data, 1, 0);
|
||||
if (data == 1)
|
||||
threads_completed++; // Thread ended
|
||||
}
|
||||
zmq_threadclose (t1);
|
||||
zmq_threadclose (t2);
|
||||
|
||||
// make the thread exit
|
||||
data[0] = 1;
|
||||
|
||||
rc = zmq_send_const(client, data, 1, 0);
|
||||
assert (rc == 1);
|
||||
|
||||
rc = zmq_send_const(client, data, 1, 0);
|
||||
assert(rc == 1);
|
||||
|
||||
zmq_threadclose(t1);
|
||||
zmq_threadclose(t2);
|
||||
|
||||
rc = zmq_close (client2);
|
||||
rc = zmq_close (server);
|
||||
assert (rc == 0);
|
||||
|
||||
rc = zmq_close (client);
|
||||
@ -104,59 +84,3 @@ int main (void)
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
void worker1(void* s)
|
||||
{
|
||||
const char worker_id = 1;
|
||||
char c;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int rc = zmq_recv(s, &c,1, 0);
|
||||
assert(rc == 1);
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
msleep(100);
|
||||
rc = zmq_send_const(s,&worker_id, 1, 0);
|
||||
assert(rc == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we got exit request
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void worker2(void* s)
|
||||
{
|
||||
const char worker_id = 2;
|
||||
char c;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int rc = zmq_recv(s, &c,1, 0);
|
||||
assert(rc == 1);
|
||||
|
||||
assert(c == 1 || c == 0);
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
msleep(100);
|
||||
rc = zmq_send_const(s,&worker_id, 1, 0);
|
||||
assert(rc == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we got exit request
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -32,7 +32,11 @@
|
||||
|
||||
#include "../include/zmq.h"
|
||||
#include "../src/stdint.hpp"
|
||||
#include "platform.hpp"
|
||||
#ifdef USING_CMAKE
|
||||
# include "platform.hpp"
|
||||
#else
|
||||
# include "../src/platform.hpp"
|
||||
#endif
|
||||
|
||||
// This defines the settle time used in tests; raise this if we
|
||||
// get test failures on slower systems due to binds/connects not
|
||||
@ -60,7 +64,6 @@
|
||||
|
||||
// Bounce a message from client to server and back
|
||||
// For REQ/REP or DEALER/DEALER pairs only
|
||||
|
||||
void
|
||||
bounce (void *server, void *client)
|
||||
{
|
||||
@ -116,7 +119,6 @@ bounce (void *server, void *client)
|
||||
|
||||
// Same as bounce, but expect messages to never arrive
|
||||
// for security or subscriber reasons.
|
||||
|
||||
void
|
||||
expect_bounce_fail (void *server, void *client)
|
||||
{
|
||||
@ -193,7 +195,9 @@ const char *SEQ_END = (const char *) 1;
|
||||
// Sends a message composed of frames that are C strings or null frames.
|
||||
// The list must be terminated by SEQ_END.
|
||||
// Example: s_send_seq (req, "ABC", 0, "DEF", SEQ_END);
|
||||
void s_send_seq (void *socket, ...)
|
||||
|
||||
void
|
||||
s_send_seq (void *socket, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, socket);
|
||||
@ -222,7 +226,9 @@ void s_send_seq (void *socket, ...)
|
||||
// the given data which can be either C strings or 0 for a null frame.
|
||||
// The list must be terminated by SEQ_END.
|
||||
// Example: s_recv_seq (rep, "ABC", 0, "DEF", SEQ_END);
|
||||
void s_recv_seq (void *socket, ...)
|
||||
|
||||
void
|
||||
s_recv_seq (void *socket, ...)
|
||||
{
|
||||
zmq_msg_t msg;
|
||||
zmq_msg_init (&msg);
|
||||
@ -260,7 +266,8 @@ void s_recv_seq (void *socket, ...)
|
||||
|
||||
|
||||
// Sets a zero linger period on a socket and closes it.
|
||||
void close_zero_linger (void *socket)
|
||||
void
|
||||
close_zero_linger (void *socket)
|
||||
{
|
||||
int linger = 0;
|
||||
int rc = zmq_setsockopt (socket, ZMQ_LINGER, &linger, sizeof(linger));
|
||||
@ -269,7 +276,8 @@ void close_zero_linger (void *socket)
|
||||
assert (rc == 0);
|
||||
}
|
||||
|
||||
void setup_test_environment()
|
||||
void
|
||||
setup_test_environment (void)
|
||||
{
|
||||
#if defined _WIN32
|
||||
# if defined _MSC_VER
|
||||
@ -296,8 +304,11 @@ void setup_test_environment()
|
||||
}
|
||||
|
||||
// Provide portable millisecond sleep
|
||||
// http://www.cplusplus.com/forum/unices/60161/ http://en.cppreference.com/w/cpp/thread/sleep_for
|
||||
void msleep (int milliseconds)
|
||||
// http://www.cplusplus.com/forum/unices/60161/
|
||||
// http://en.cppreference.com/w/cpp/thread/sleep_for
|
||||
|
||||
void
|
||||
msleep (int milliseconds)
|
||||
{
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
Sleep (milliseconds);
|
||||
|
Loading…
x
Reference in New Issue
Block a user