summaryrefslogtreecommitdiff
path: root/ref/print.html
diff options
context:
space:
mode:
Diffstat (limited to 'ref/print.html')
-rw-r--r--ref/print.html147
1 files changed, 138 insertions, 9 deletions
diff --git a/ref/print.html b/ref/print.html
index 6ac7695d..b7725ff0 100644
--- a/ref/print.html
+++ b/ref/print.html
@@ -1328,17 +1328,96 @@ For example, the message may be sitting in queue, or located in TCP buffers, or
steps on the part of the application, the lowest latencies and highest performance will be achieved by using
this function instead of <a href="api//api/sock.html#nng_send"><code>nng_send</code></a> or <a href="api//api/sock.html#nng_sendmsg"><code>nng_sendmsg</code></a>.</p>
</div>
+<h2 id="receiving-messages"><a class="header" href="#receiving-messages">Receiving Messages</a></h2>
+<pre><code class="language-c">int nng_recv(nng_socket s, void *data, size_t *sizep, int flags);
+int nng_recvmsg(nng_socket s, nng_msg **msgp, int flags);
+void nng_recv_aio(nng_socket s, nng_aio *aio);
+</code></pre>
+<p>These functions (<a name="a039"></a><code>nng_recv</code>, <a name="a040"></a><code>nng_recvmsg</code>, and <a name="a041"></a><code>nng_recv_aio</code>) receive
+messages over the socket <em>s</em>. The differences in their behaviors are as follows.</p>
+<div class="mdbook-alerts mdbook-alerts-note">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ note
+</p>
+<p>The semantics of what receving a message means varies from protocol to
+protocol, so examination of the protocol documentation is encouraged.
+Additionally, some protocols may not support receiving at all or may require other pre-conditions first.
+(For example, <a href="api//proto/req.html">REQ</a> sockets cannot normally receive data until they have first sent a request,
+while <a href="api//proto/pub.html">PUB</a> sockets can only send data and never receive it.)</p>
+</div>
+<h3 id="nng_recv"><a class="header" href="#nng_recv">nng_recv</a></h3>
+<p>The <code>nng_recv</code> function is the simplest to use, but is the least efficient.
+It receives the content in <em>data</em>, as a message size (in bytes) of up to the value stored in <em>sizep</em>,
+unless the <code>NNG_FLAG_ALLOC</code> flag is set in <em>flags</em> (see below.)</p>
+<p>Upon success, the size of the message received will be stored in <em>sizep</em>.</p>
+<p>The <em>flags</em> is a bit mask made up of zero or more of the following values:</p>
+<ul>
+<li>
+<p><a name="a042"></a><code>NNG_FLAG_NONBLOCK</code>:
+If the socket has no messages pending for reception at this time, it does not block, but returns immediately
+with a status of <a href="api//api/errors.html#NNG_EAGAIN"><code>NNG_EAGAIN</code></a>. If this flag is absent, the function will wait until data can be received.</p>
+</li>
+<li>
+<p><a name="a043"></a><code>NNG_FLAG_ALLOC</code>:
+Instead of receiving the message into <em>data</em>, a new buffer will be allocated exactly large enough to hold
+the message. A pointer to that buffer will be stored at the location specified by <em>data</em>. This provides a form
+of zero-copy operation. The caller should dispose of the buffer using <a href="api//api/memory.html#deallocate-memory"><code>nng_free</code></a> or by sending using
+<a href="api//api/sock.html#nng_send"><code>nng_send</code></a> with the <a href="api//TODO.html"><code>NNG_FLAG_ALLOC</code></a> flag.</p>
+</li>
+</ul>
+<div class="mdbook-alerts mdbook-alerts-important">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ important
+</p>
+<p>When using <code>NNG_FLAG_ALLOC</code>, it is important that the value of <em>size</em> match the actual allocated size of the data.
+Using an incorrect size results in unspecified behavior, which may include heap corruption, program crashes,
+or other undesirable effects.</p>
+</div>
+<h3 id="nng_recvmsg"><a class="header" href="#nng_recvmsg">nng_recvmsg</a></h3>
+<p>The <code>nng_recvmsg</code> function receives a message and stores a pointer to the <a href="api//api/msg.html#message-structure"><code>nng_msg</code></a> for that message in <em>msgp</em>.</p>
+<p>The <em>flags</em> can contain the value <a href="api//TODO.html"><code>NNG_FLAG_NONBLOCK</code></a>, indicating that the function should not wait if the socket
+has no messages available to receive. In such a case, it will return <a href="api//api/errors.html#NNG_EAGAIN"><code>NNG_EAGAIN</code></a>.</p>
+<div class="mdbook-alerts mdbook-alerts-tip">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ tip
+</p>
+<p>This function is preferred over <a href="api//TODO.html"><code>nng_recv</code></a>, as it gives access to the message structure and eliminates both
+a data copy and allocation, even when <code>nng_recv</code> is using <code>NNG_FLAG_ALLOC</code>.</p>
+</div>
+<h3 id="nng_recv_aio"><a class="header" href="#nng_recv_aio">nng_recv_aio</a></h3>
+<p>The <code>nng_send_aio</code> function receives a message asynchronously, using the <a href="api//api/aio.html#asynchronous-io-handle"><code>nng_aio</code></a> <em>aio</em>, over the socket <em>s</em>.
+On success, the received message can be retrieved from the <em>aio</em> using the <a href="api//api/aio.html#messages"><code>nng_aio_get_msg</code></a> function.</p>
+<div class="mdbook-alerts mdbook-alerts-note">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ note
+</p>
+<p>It is important that the application retrieves the message, and disposes of it accordingly.
+Failure to do so will leak the memory.</p>
+</div>
+<div class="mdbook-alerts mdbook-alerts-tip">
+<p class="mdbook-alerts-title">
+ <span class="mdbook-alerts-icon"></span>
+ tip
+</p>
+<p>This is the preferred function to use for receiving data on a socket. While it does require a few extra
+steps on the part of the application, the lowest latencies and highest performance will be achieved by using
+this function instead of <a href="api//TODO.html"><code>nng_recv</code></a> or <a href="api//TODO.html"><code>nng_recvmsg</code></a>.</p>
+</div>
<h2 id="polling-socket-events"><a class="header" href="#polling-socket-events">Polling Socket Events</a></h2>
<pre><code class="language-c">int nng_socket_get_recv_poll_fd(nng_socket s, int *fdp);
int nng_socket_get_send_poll_fd(nng_socket s, int *fdp);
</code></pre>
<p>Sometimes it is necessary to integrate a socket into a <code>poll</code> or <code>select</code> driven
-<a name="a039"></a>event loop. (Or, on Linux, <code>epoll</code>, or on BSD derived systems like macOS <code>kqueue</code>).</p>
+<a name="a044"></a>event loop. (Or, on Linux, <code>epoll</code>, or on BSD derived systems like macOS <code>kqueue</code>).</p>
<p>For these occasions, a suitable file descriptor for polling is provided
by these two functions.</p>
-<p>The <a name="a040"></a><code>nng_socket_get_recv_poll_fd</code> function obtains a file descriptor
+<p>The <a name="a045"></a><code>nng_socket_get_recv_poll_fd</code> function obtains a file descriptor
that will poll as readable when a message is ready for receiving for the socket.</p>
-<p>The <a name="a041"></a><code>nng_socket_get_send_poll_fd</code> function obtains a file descriptor
+<p>The <a name="a046"></a><code>nng_socket_get_send_poll_fd</code> function obtains a file descriptor
that will poll as readable when the socket can accept a message for sending.</p>
<p>These file descriptors should only be polled for readability, and no
other operation performed on them. The socket will read from, or write to,
@@ -1380,6 +1459,7 @@ when possible.</p>
build a service that publishes a timestamp at one second intervals. Error handling is elided for the
sake of clarity.</p>
<pre><code class="language-c">#include &lt;stdlib.h&gt;
+#include &lt;stdio.h&gt;
#include &lt;nng/nng.h&gt;
#include &lt;nng/protocol/pubsub0/pub.h&gt;
@@ -1396,7 +1476,7 @@ void callback(void *arg) {
nng_time now;
struct state *state = arg;
if (nng_aio_result(state-&gt;aio) != 0) {
- nng_log_err("Error %s occurred", nng_strerror(nng_aio_result(state-&gt;aio)));
+ fprintf(stderr, "Error %s occurred", nng_strerror(nng_aio_result(state-&gt;aio)));
return; // terminate the callback loop
}
if (state-&gt;sleeping) {
@@ -1425,6 +1505,52 @@ int main(int argc, char **argv) {
}
}
</code></pre>
+<h3 id="example-3-watching-a-periodic-timestamp"><a class="header" href="#example-3-watching-a-periodic-timestamp">Example 3: Watching a Periodic Timestamp</a></h3>
+<p>This example demonstrates the use of <a href="api//api/aio.html#asynchronous-io-handle"><code>nng_aio</code></a>, [<code>nng_recv_aio</code>], to build a client to
+watch for messages received from the service created in Example 2.
+Error handling is elided for the sake of clarity.</p>
+<pre><code class="language-c">#include &lt;stdlib.h&gt;
+#include &lt;stdio.h&gt;
+#include &lt;string.h&gt;&gt;
+#include &lt;nng/nng.h&gt;
+#include &lt;nng/protocol/pubsub0/sub.h&gt;
+
+struct state {
+ nng_socket s;
+ nng_aio *aio;
+};
+
+static struct state state;
+
+void callback(void *arg) {
+ nng_msg *msg;
+ nng_time now;
+ struct state *state = arg;
+ if (nng_aio_result(state-&gt;aio) != 0) {
+ fprintf(stderr, "Error %s occurred", nng_strerror(nng_aio_result(state-&gt;aio)));
+ return; // terminate the callback loop
+ }
+ msg = nng_aio_get_msg(state-&gt;aio);
+ memcpy(&amp;now, nng_msg_body(msg), sizeof (now)); // should check the length!
+ printf("Timestamp is %lu\n", (unsigned long)now);
+ nng_msg_free(msg);
+ nng_aio_set_msg(state-&gt;aio, NULL);
+ nng_recv_aio(state-&gt;s, state-&gt;aio);
+}
+
+int main(int argc, char **argv) {
+ const char *url = argv[1]; // should check this
+
+ nng_aio_alloc(&amp;state.aio, NULL, NULL);
+ nng_sub0_open(&amp;state.s);
+ nng_sub0_socket_subscribe(state.s, NULL, 0); // subscribe to everything
+ nng_dial(state.s, url, NULL, 0);
+ nng_recv_aio(state.s, state.aio); // kick it off right away
+ for(;;) {
+ nng_msleep(0x7FFFFFFF); // infinite, could use pause or sigsuspend
+ }
+}
+</code></pre>
<!-- Symbol cross reference -->
<!-- Macros -->
<!-- Protocols -->
@@ -6473,7 +6599,7 @@ condition variable, <a href="api/synch.html#a009">1</a><br/>
CPU-bound, <a href="api/thread.html#a003">1</a><br/>
duration, <a href="api/time.html#a003">1</a><br/>
error message, <a href="api/errors.html#a002">1</a><br/>
-event loop, <a href="api/sock.html#a039">1</a><br/>
+event loop, <a href="api/sock.html#a044">1</a><br/>
flow control, <a href="proto/index.html#a006">1</a><br/>
gather, <a href="api/aio.html#a024">1</a><br/>
<code>getopt</code>, <a href="api/cmd_opts.html#a003">1</a><br/>
@@ -6531,8 +6657,8 @@ named pipes, <a href="tran/ipc.html#a004">1</a><br/>
<code>NNG_DURATION_ZERO</code>, <a href="api/time.html#a006">1</a><br/>
<code>NNG_ECANCELED</code>, <a href="api/aio.html#a010">1</a><br/>
<code>nng_fini</code>, <a href="api/init.html#a002">1</a><br/>
-<code>NNG_FLAG_ALLOC</code>, <a href="api/sock.html#a038">1</a><br/>
-<code>NNG_FLAG_NONBLOCK</code>, <a href="api/sock.html#a037">1</a><br/>
+<code>NNG_FLAG_ALLOC</code>, <a href="api/sock.html#a038">1</a>, <a href="api/sock.html#a043">2</a><br/>
+<code>NNG_FLAG_NONBLOCK</code>, <a href="api/sock.html#a037">1</a>, <a href="api/sock.html#a042">2</a><br/>
<code>nng_free</code>, <a href="api/memory.html#a004">1</a><br/>
<code>nng_id_alloc</code>, <a href="api/id_map.html#a006">1</a><br/>
<code>nng_id_get</code>, <a href="api/id_map.html#a005">1</a><br/>
@@ -6605,6 +6731,9 @@ named pipes, <a href="tran/ipc.html#a004">1</a><br/>
<code>nng_push0_open</code>, <a href="api/sock.html#a015">1</a><br/>
<code>nng_push0_open_raw</code>, <a href="api/sock.html#a027">1</a><br/>
<code>nng_random</code>, <a href="api/misc.html#a001">1</a><br/>
+<code>nng_recv</code>, <a href="api/sock.html#a039">1</a><br/>
+<code>nng_recv_aio</code>, <a href="api/sock.html#a041">1</a><br/>
+<code>nng_recvmsg</code>, <a href="api/sock.html#a040">1</a><br/>
<code>nng_rep0_open</code>, <a href="api/sock.html#a016">1</a><br/>
<code>nng_rep0_open_raw</code>, <a href="api/sock.html#a028">1</a><br/>
<code>nng_req0_open</code>, <a href="api/sock.html#a017">1</a><br/>
@@ -6617,8 +6746,8 @@ named pipes, <a href="tran/ipc.html#a004">1</a><br/>
<code>nng_sleep_aio</code>, <a href="api/time.html#a011">1</a><br/>
<code>nng_socket</code>, <a href="api/sock.html#a002">1</a><br/>
<code>nng_socket_close</code>, <a href="api/sock.html#a033">1</a><br/>
-<code>nng_socket_get_recv_poll_fd</code>, <a href="api/sock.html#a040">1</a><br/>
-<code>nng_socket_get_send_poll_fd</code>, <a href="api/sock.html#a041">1</a><br/>
+<code>nng_socket_get_recv_poll_fd</code>, <a href="api/sock.html#a045">1</a><br/>
+<code>nng_socket_get_send_poll_fd</code>, <a href="api/sock.html#a046">1</a><br/>
<code>nng_socket_id</code>, <a href="api/sock.html#a003">1</a><br/>
<code>nng_socket_peer_id</code>, <a href="api/sock.html#a005">1</a><br/>
<code>nng_socket_peer_name</code>, <a href="api/sock.html#a007">1</a><br/>