From 4382b309d91ae0b6dff0399ecb058656e2b32eb1 Mon Sep 17 00:00:00 2001 From: ainsley Date: Wed, 26 Aug 2020 09:29:26 -0500 Subject: [PATCH] Add C Client examples --- developing-with-nats/connecting/cluster.md | 21 +++ .../connecting/connect_timeout.md | 21 +++ .../connecting/default_server.md | 14 ++ developing-with-nats/connecting/misc.md | 65 ++++++++++ developing-with-nats/connecting/name.md | 20 +++ developing-with-nats/connecting/noecho.md | 20 +++ developing-with-nats/connecting/pingpong.md | 24 ++++ .../connecting/specific_server.md | 18 +++ developing-with-nats/events/events.md | 122 ++++++++++++++++++ developing-with-nats/events/slow.md | 64 +++++++++ developing-with-nats/receiving/async.md | 39 ++++++ developing-with-nats/receiving/drain.md | 102 +++++++++++++++ developing-with-nats/receiving/queues.md | 36 ++++++ developing-with-nats/receiving/reply.md | 38 ++++++ developing-with-nats/receiving/structure.md | 6 + developing-with-nats/receiving/sync.md | 36 ++++++ developing-with-nats/receiving/unsub_after.md | 40 ++++++ .../receiving/unsubscribing.md | 24 ++++ developing-with-nats/receiving/wildcards.md | 68 ++++++++++ developing-with-nats/reconnect/buffer.md | 21 +++ developing-with-nats/reconnect/disable.md | 20 +++ developing-with-nats/reconnect/events.md | 41 ++++++ developing-with-nats/reconnect/max.md | 20 +++ developing-with-nats/reconnect/random.md | 22 ++++ developing-with-nats/reconnect/wait.md | 21 +++ developing-with-nats/security/creds.md | 23 ++++ developing-with-nats/security/nkey.md | 40 ++++++ developing-with-nats/security/tls.md | 22 ++++ developing-with-nats/security/token.md | 40 ++++++ developing-with-nats/security/userpass.md | 40 ++++++ developing-with-nats/sending/caches.md | 23 ++++ developing-with-nats/sending/replyto.md | 18 +++ developing-with-nats/sending/request_reply.md | 30 +++++ developing-with-nats/sending/structure.md | 6 + 34 files changed, 1165 insertions(+) diff --git a/developing-with-nats/connecting/cluster.md b/developing-with-nats/connecting/cluster.md index b65f558..da8ab65 100644 --- a/developing-with-nats/connecting/cluster.md +++ b/developing-with-nats/connecting/cluster.md @@ -110,5 +110,26 @@ let nc = await connect({ nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; +const char *servers[] = {"nats://127.0.0.1:1222", "nats://127.0.0.1:1223", "nats://127.0.0.1:1224"}; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetServers(opts, servers, 3); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/connecting/connect_timeout.md b/developing-with-nats/connecting/connect_timeout.md index 1c4ed7a..7a4c2eb 100644 --- a/developing-with-nats/connecting/connect_timeout.md +++ b/developing-with-nats/connecting/connect_timeout.md @@ -85,5 +85,26 @@ let nc = await connect({ }); ``` {% endtab %} + +{% tab title="C" %} +```c +nnatsConnection *conn = NULL; + natsOptions *opts = NULL; + natsStatus s = NATS_OK; + + s = natsOptions_Create(&opts); + if (s == NATS_OK) + // Set the timeout to 10 seconds (10,000 milliseconds) + s = natsOptions_SetTimeout(opts, 10000); + if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + + (...) + + // Destroy objects that were created + natsConnection_Destroy(conn); + natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/connecting/default_server.md b/developing-with-nats/connecting/default_server.md index a74978e..44f0450 100644 --- a/developing-with-nats/connecting/default_server.md +++ b/developing-with-nats/connecting/default_server.md @@ -85,5 +85,19 @@ connect() // add a .catch/.finally ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsStatus s; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); +if (s != NATS_OK) + // handle error + +// Destroy connection, no-op if conn is NULL. +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/connecting/misc.md b/developing-with-nats/connecting/misc.md index 18fb9dc..474d4b6 100644 --- a/developing-with-nats/connecting/misc.md +++ b/developing-with-nats/connecting/misc.md @@ -89,6 +89,25 @@ nc.on('connect', (nc: Client, url: string, options: ServerInfo) => { }); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsStatus s = NATS_OK; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); +if (s == NATS_OK) +{ + int64_t mp = natsConnection_GetMaxPayload(conn); + printf("Max payload: %d\n", (int) mp); +} + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} ## Turn On Pedantic Mode @@ -178,6 +197,26 @@ let nc = await connect({ nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetPedantic(opts, true); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} ## Set the Maximum Control Line Size @@ -236,6 +275,12 @@ let nc = NATS.connect({ // control line size is not configurable on TypeScript NATS client. ``` {% endtab %} + +{% tab title="C" %} +```c +// control line is not configurable on C NATS client. +``` +{% endtab %} {% endtabs %} ## Turn On/Off Verbose Mode @@ -325,5 +370,25 @@ let nc = await connect({ nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetVerbose(opts, true); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/connecting/name.md b/developing-with-nats/connecting/name.md index b5dbd0e..aacbbe3 100644 --- a/developing-with-nats/connecting/name.md +++ b/developing-with-nats/connecting/name.md @@ -86,5 +86,25 @@ let nc = await connect({ nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetName(opts, "API Name Option Example"); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/connecting/noecho.md b/developing-with-nats/connecting/noecho.md index d3b369b..4431af3 100644 --- a/developing-with-nats/connecting/noecho.md +++ b/developing-with-nats/connecting/noecho.md @@ -84,5 +84,25 @@ let nc = await connect({ url: "nats://demo.nats.io:4222", noEcho: true}); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetNoEcho(opts, true); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/connecting/pingpong.md b/developing-with-nats/connecting/pingpong.md index a5fd080..a669d26 100644 --- a/developing-with-nats/connecting/pingpong.md +++ b/developing-with-nats/connecting/pingpong.md @@ -93,5 +93,29 @@ let nc = await connect({ nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + // Set Ping interval to 20 seconds (20,000 milliseconds) + s = natsOptions_SetPingInterval(opts, 20000); +if (s == NATS_OK) + // Set the limit to 5 + s = natsOptions_SetMaxPingsOut(opts, 5); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/connecting/specific_server.md b/developing-with-nats/connecting/specific_server.md index c0bcc1e..23b46a3 100644 --- a/developing-with-nats/connecting/specific_server.md +++ b/developing-with-nats/connecting/specific_server.md @@ -82,5 +82,23 @@ end nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsStatus s; + +// If connecting to the default port, the URL can be simplified +// to just the hostname/IP. +// That is, the connect below is equivalent to: +// natsConnection_ConnectTo(&conn, "nats://demo.nats.io:4222"); +s = natsConnection_ConnectTo(&conn, "demo.nats.io"); +if (s != NATS_OK) + // handle error + +// Destroy connection, no-op if conn is NULL. +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/events/events.md b/developing-with-nats/events/events.md index 8cfe52f..727fce2 100644 --- a/developing-with-nats/events/events.md +++ b/developing-with-nats/events/events.md @@ -168,6 +168,53 @@ nc.on('reconnect', (nc, url) => { }); ``` {% endtab %} + +{% tab title="C" %} +```c +static void +disconnectedCB(natsConnection *conn, void *closure) +{ + // Do something + printf("Connection disconnected\n"); +} + +static void +reconnectedCB(natsConnection *conn, void *closure) +{ + // Do something + printf("Connection reconnected\n"); +} + +static void +closedCB(natsConnection *conn, void *closure) +{ + // Do something + printf("Connection closed\n"); +} + +(...) + +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetDisconnectedCB(opts, disconnectedCB, NULL); +if (s == NATS_OK) + s = natsOptions_SetReconnectedCB(opts, reconnectedCB, NULL); +if (s == NATS_OK) + s = natsOptions_SetClosedCB(opts, closedCB, NULL); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} ## Listen for New Servers @@ -254,6 +301,52 @@ nc.on('serversChanged', (ce) => { }); ``` {% endtab %} + +{% tab title="C" %} +```c +static void +discoveredServersCB(natsConnection *conn, void *closure) +{ + natsStatus s = NATS_OK; + char **servers = NULL; + int count = 0; + + s = natsConnection_GetDiscoveredServers(conn, &servers, &count); + if (s == NATS_OK) + { + int i; + + // Do something... + for (i=0; i { }); ``` {% endtab %} + +{% tab title="C" %} +```c +static void +errorCB(natsConnection *conn, natsSubscription *sub, natsStatus s, void *closure) +{ + // Do something + printf("Error: %d - %s\n", s, natsStatus_GetText(s)); +} + +(...) + +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetErrorHandler(opts, errorCB, NULL); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/events/slow.md b/developing-with-nats/events/slow.md index 4082322..3ffbd58 100644 --- a/developing-with-nats/events/slow.md +++ b/developing-with-nats/events/slow.md @@ -110,6 +110,40 @@ await nc.subscribe("updates", cb=cb, pending_bytes_limit=5*1024*1024, pending_ms // slow pending limits are not configurable on TypeScript NATS client. ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsSubscription *sub1 = NULL; +natsSubscription *sub2 = NULL; +natsStatus s = NATS_OK; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); + +// Subscribe +if (s == NATS_OK) + s = natsConnection_Subscribe(&sub1, conn, "updates", onMsg, NULL); + +// Set limits of 1000 messages or 5MB, whichever comes first +if (s == NATS_OK) + s = natsSubscription_SetPendingLimits(sub1, 1000, 5*1024*1024); + +// Subscribe +if (s == NATS_OK) + s = natsConnection_Subscribe(&sub2, conn, "updates", onMsg, NULL); + +// Set no limits for this subscription +if (s == NATS_OK) + s = natsSubscription_SetPendingLimits(sub2, -1, -1); + +(...) + +// Destroy objects that were created +natsSubscription_Destroy(sub1); +natsSubscription_Destroy(sub2); +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} ## Detect a Slow Consumer and Check for Dropped Messages @@ -232,5 +266,35 @@ public class SlowConsumerListener { // slow consumer detection is not configurable on NATS TypeScript client. ``` {% endtab %} + +{% tab title="C" %} +```c +static void +errorCB(natsConnection *conn, natsSubscription *sub, natsStatus s, void *closure) +{ + + // Do something + printf("Error: %d - %s", s, natsStatus_GetText(s)); +} + +(...) + +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetErrorHandler(opts, errorCB, NULL); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/receiving/async.md b/developing-with-nats/receiving/async.md index 5466219..ccb5ae4 100644 --- a/developing-with-nats/receiving/async.md +++ b/developing-with-nats/receiving/async.md @@ -114,5 +114,44 @@ nc.subscribe("updates", (err, msg) => { }); ``` {% endtab %} + +{% tab title="C" %} +```c +static void +onMsg(natsConnection *conn, natsSubscription *sub, natsMsg *msg, void *closure) +{ + printf("Received msg: %s - %.*s\n", + natsMsg_GetSubject(msg), + natsMsg_GetDataLength(msg), + natsMsg_GetData(msg)); + + // Need to destroy the message! + natsMsg_Destroy(msg); +} + +(...) + +natsConnection *conn = NULL; +natsSubscription *sub = NULL; +natsStatus s; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); +if (s == NATS_OK) +{ + // Creates an asynchronous subscription on subject "foo". + // When a message is sent on subject "foo", the callback + // onMsg() will be invoked by the client library. + // You can pass a closure as the last argument. + s = natsConnection_Subscribe(&sub, conn, "foo", onMsg, NULL); +} + +(...) + + +// Destroy objects that were created +natsSubscription_Destroy(sub); +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/receiving/drain.md b/developing-with-nats/receiving/drain.md index 2229274..45a2c3d 100644 --- a/developing-with-nats/receiving/drain.md +++ b/developing-with-nats/receiving/drain.md @@ -202,6 +202,73 @@ await nc.drain(); nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +static void +onMsg(natsConnection *conn, natsSubscription *sub, natsMsg *msg, void *closure) +{ + printf("Received msg: %s - %.*s\n", + natsMsg_GetSubject(msg), + natsMsg_GetDataLength(msg), + natsMsg_GetData(msg)); + + // Add some delay while processing + nats_Sleep(200); + + // Need to destroy the message! + natsMsg_Destroy(msg); +} + +static void +closeHandler(natsConnection *conn, void *closure) +{ + cond_variable cv = (cond_variable) closure; + + notify_cond_variable(cv); +} + +(...) + + +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsSubscription *sub = NULL; +natsStatus s = NATS_OK; +cond_variable cv = new_cond_variable(); // some fictuous way to notify between threads. + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + // Setup a close handler and pass a reference to our condition variable. + s = natsOptions_SetClosedCB(opts, closeHandler, (void*) cv); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +// Subscribe +if (s == NATS_OK) + s = natsConnection_Subscribe(&sub, conn, "foo", onMsg, NULL); + +// Publish a message +if (s == NATS_OK) + s = natsConnection_PublishString(conn, "foo", "hello"); + +// Drain the connection, which will close it when done. +if (s == NATS_OK) + s = natsConnection_Drain(conn); + +// Wait for the connection to be closed +if (s == NATS_OK) + cond_variable_wait(cv); + +(...) + +// Destroy objects that were created +natsSubscription_Destroy(sub); +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} + {% endtabs %} The mechanics of drain for a subscription are simpler: @@ -366,6 +433,41 @@ let sub = await nc.subscribe('updates', (err, msg) => { }, {queue: "workers"}); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsSubscription *sub = NULL; +natsStatus s = NATS_OK; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); + +// Subscribe +if (s == NATS_OK) + s = natsConnection_Subscribe(&sub, conn, "foo", onMsg, NULL); + +// Publish 2 messages +if (s == NATS_OK) +{ + int i; + for (i=0; (s == NATS_OK) && (i<2); i++) + { + s = natsConnection_PublishString(conn, "foo", "hello"); + } +} + +// Call Drain on the subscription. It unsubscribes but +// wait for all pending messages to be processed. +if (s == NATS_OK) + s = natsSubscription_Drain(sub); + +(...) + +// Destroy objects that were created +natsSubscription_Destroy(sub); +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} Because draining can involve messages flowing to the server, for a flush and asynchronous message processing, the timeout for drain should generally be higher than the timeout for a simple message request/reply or similar. diff --git a/developing-with-nats/receiving/queues.md b/developing-with-nats/receiving/queues.md index 398e81b..4b8ed48 100644 --- a/developing-with-nats/receiving/queues.md +++ b/developing-with-nats/receiving/queues.md @@ -119,6 +119,42 @@ await nc.subscribe('updates', (err, msg) => { }, {queue: "workers"}); ``` {% endtab %} + +{% tab title="C" %} +```c +static void +onMsg(natsConnection *conn, natsSubscription *sub, natsMsg *msg, void *closure) +{ + printf("Received msg: %s - %.*s\n", + natsMsg_GetSubject(msg), + natsMsg_GetDataLength(msg), + natsMsg_GetData(msg)); + + // Need to destroy the message! + natsMsg_Destroy(msg); +} + + +(...) + +natsConnection *conn = NULL; +natsSubscription *sub = NULL; +natsStatus s; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); + +// Create a queue subscription on "updates" with queue name "workers" +if (s == NATS_OK) + s = natsConnection_QueueSubscribe(&sub, conn, "updates", "workers", onMsg, NULL); + +(...) + + +// Destroy objects that were created +natsSubscription_Destroy(sub); +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} If you run this example with the publish examples that send to `updates`, you will see that one of the instances gets a message while the others you run won't. But the instance that receives the message will change. diff --git a/developing-with-nats/receiving/reply.md b/developing-with-nats/receiving/reply.md index 8f292c5..345d54f 100644 --- a/developing-with-nats/receiving/reply.md +++ b/developing-with-nats/receiving/reply.md @@ -134,5 +134,43 @@ await nc.subscribe('time', (err, msg) => { }); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsSubscription *sub = NULL; +natsMsg *msg = NULL; +natsStatus s = NATS_OK; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); + +// Subscribe +if (s == NATS_OK) + s = natsConnection_SubscribeSync(&sub, conn, "time"); + +// Wait for messages +if (s == NATS_OK) + s = natsSubscription_NextMsg(&msg, sub, 10000); + +if (s == NATS_OK) +{ + char buf[64]; + + snprintf(buf, sizeof(buf), "%lld", nats_Now()); + + // Send the time as a response + s = natsConnection_Publish(conn, natsMsg_GetReply(msg), buf, (int) strlen(buf)); + + // Destroy message that was received + natsMsg_Destroy(msg); +} + +(...) + +// Destroy objects that were created +natsSubscription_Destroy(sub); +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/receiving/structure.md b/developing-with-nats/receiving/structure.md index 709f19d..b5c9585 100644 --- a/developing-with-nats/receiving/structure.md +++ b/developing-with-nats/receiving/structure.md @@ -168,5 +168,11 @@ nc.subscribe('updates', (err, msg) => { }); ``` {% endtab %} + +{% tab title="C" %} +```c +// Structured data is not configurable in C NATS Client. +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/receiving/sync.md b/developing-with-nats/receiving/sync.md index f314103..6f03eae 100644 --- a/developing-with-nats/receiving/sync.md +++ b/developing-with-nats/receiving/sync.md @@ -71,5 +71,41 @@ nc.close(); / Typescript NATS subscriptions are always async. ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsSubscription *sub = NULL; +natsMsg *msg = NULL; +natsStatus s = NATS_OK; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); + +// Subscribe +if (s == NATS_OK) + s = natsConnection_SubscribeSync(&sub, conn, "updates"); + +// Wait for messages +if (s == NATS_OK) + s = natsSubscription_NextMsg(&msg, sub, 10000); + +if (s == NATS_OK) +{ + printf("Received msg: %s - %.*s\n", + natsMsg_GetSubject(msg), + natsMsg_GetDataLength(msg), + natsMsg_GetData(msg)); + + // Destroy message that was received + natsMsg_Destroy(msg); +} + +(...) + +// Destroy objects that were created +natsSubscription_Destroy(sub); +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/receiving/unsub_after.md b/developing-with-nats/receiving/unsub_after.md index ecf2f58..b516c46 100644 --- a/developing-with-nats/receiving/unsub_after.md +++ b/developing-with-nats/receiving/unsub_after.md @@ -143,5 +143,45 @@ let sub2 = await nc.subscribe(createInbox(), (err, msg) => { sub2.unsubscribe(10); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsSubscription *sub = NULL; +natsMsg *msg = NULL; +natsStatus s = NATS_OK; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); + +// Subscribe +if (s == NATS_OK) + s = natsConnection_SubscribeSync(&sub, conn, "updates"); + +// Unsubscribe after 1 message is received +if (s == NATS_OK) + s = natsSubscription_AutoUnsubscribe(sub, 1); + +// Wait for messages +if (s == NATS_OK) + s = natsSubscription_NextMsg(&msg, sub, 10000); + +if (s == NATS_OK) +{ + printf("Received msg: %s - %.*s\n", + natsMsg_GetSubject(msg), + natsMsg_GetDataLength(msg), + natsMsg_GetData(msg)); + + // Destroy message that was received + natsMsg_Destroy(msg); +} + +(...) + +// Destroy objects that were created +natsSubscription_Destroy(sub); +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/receiving/unsubscribing.md b/developing-with-nats/receiving/unsubscribing.md index a0c19d6..fa9bef7 100644 --- a/developing-with-nats/receiving/unsubscribing.md +++ b/developing-with-nats/receiving/unsubscribing.md @@ -140,5 +140,29 @@ let sub = await nc.subscribe(createInbox(), (err, msg) => { sub.unsubscribe(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsSubscription *sub = NULL; +natsStatus s = NATS_OK; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); + +// Subscribe +if (s == NATS_OK) + s = natsConnection_SubscribeSync(&sub, conn, "updates"); + +// Unsubscribe +if (s == NATS_OK) + s = natsSubscription_Unsubscribe(sub); + +(...) + +// Destroy objects that were created +natsSubscription_Destroy(sub); +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/receiving/wildcards.md b/developing-with-nats/receiving/wildcards.md index 6bd18ca..8d0c74d 100644 --- a/developing-with-nats/receiving/wildcards.md +++ b/developing-with-nats/receiving/wildcards.md @@ -165,6 +165,40 @@ await nc.subscribe('time.us.*', (err, msg) => { }); ``` {% endtab %} + +{% tab title="C" %} +```c +static void +onMsg(natsConnection *conn, natsSubscription *sub, natsMsg *msg, void *closure) +{ + printf("Received msg: %s - %.*s\n", + natsMsg_GetSubject(msg), + natsMsg_GetDataLength(msg), + natsMsg_GetData(msg)); + + // Need to destroy the message! + natsMsg_Destroy(msg); +} + + +(...) + +natsConnection *conn = NULL; +natsSubscription *sub = NULL; +natsStatus s; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); +if (s == NATS_OK) + s = natsConnection_Subscribe(&sub, conn, "time.*.east", onMsg, NULL); + +(...) + + +// Destroy objects that were created +natsSubscription_Destroy(sub); +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} or do something similar with `>`: @@ -335,6 +369,40 @@ await nc.subscribe('time.>', (err, msg) => { }); ``` {% endtab %} + +{% tab title="C" %} +```c +static void +onMsg(natsConnection *conn, natsSubscription *sub, natsMsg *msg, void *closure) +{ + printf("Received msg: %s - %.*s\n", + natsMsg_GetSubject(msg), + natsMsg_GetDataLength(msg), + natsMsg_GetData(msg)); + + // Need to destroy the message! + natsMsg_Destroy(msg); +} + + +(...) + +natsConnection *conn = NULL; +natsSubscription *sub = NULL; +natsStatus s; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); +if (s == NATS_OK) + s = natsConnection_Subscribe(&sub, conn, "time.>", onMsg, NULL); + +(...) + + +// Destroy objects that were created +natsSubscription_Destroy(sub); +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} The following example can be used to test these two subscribers. The `*` subscriber should receive at most 2 messages, while the `>` subscriber receives 4. More importantly the `time.*.east` subscriber won't receive on `time.us.east.atlanta` because that won't match. diff --git a/developing-with-nats/reconnect/buffer.md b/developing-with-nats/reconnect/buffer.md index 8cbb616..df9a20c 100644 --- a/developing-with-nats/reconnect/buffer.md +++ b/developing-with-nats/reconnect/buffer.md @@ -59,6 +59,27 @@ nc.close(); // Reconnect buffer size is not configurable on NATS Typescript client ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + // Set reconnect buffer size in bytes (5 MB) + s = natsOptions_SetReconnectBufSize(opts, 5*1024*1024); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} > _As mentioned throughout this document, each client library may behave slightly differently. Please check the documentation for the library you are using._ diff --git a/developing-with-nats/reconnect/disable.md b/developing-with-nats/reconnect/disable.md index f8ed03c..2fe9456 100644 --- a/developing-with-nats/reconnect/disable.md +++ b/developing-with-nats/reconnect/disable.md @@ -80,5 +80,25 @@ let nc = await connect({ nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetAllowReconnect(opts, false); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/reconnect/events.md b/developing-with-nats/reconnect/events.md index 82036a4..89b7535 100644 --- a/developing-with-nats/reconnect/events.md +++ b/developing-with-nats/reconnect/events.md @@ -112,5 +112,46 @@ nc.on('reconnect', (conn, server) => { nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +static void +disconnectedCB(natsConnection *conn, void *closure) +{ + // Handle disconnect error event +} + +static void +reconnectedCB(natsConnection *conn, void *closure) +{ + // Handle reconnect event +} + +(...) + +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); + +// Connection event handlers are invoked asynchronously +// and the state of the connection may have changed when +// the callback is invoked. +if (s == NATS_OK) + s = natsOptions_SetDisconnectedCB(opts, disconnectedCB, NULL); +if (s == NATS_OK) + s = natsOptions_SetReconnectedCB(opts, reconnectedCB, NULL); + +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/reconnect/max.md b/developing-with-nats/reconnect/max.md index 1df99b5..490b3c6 100644 --- a/developing-with-nats/reconnect/max.md +++ b/developing-with-nats/reconnect/max.md @@ -75,5 +75,25 @@ let nc = await connect({ nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetMaxReconnect(opts, 10); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/reconnect/random.md b/developing-with-nats/reconnect/random.md index 7d07260..baf586f 100644 --- a/developing-with-nats/reconnect/random.md +++ b/developing-with-nats/reconnect/random.md @@ -90,5 +90,27 @@ let nc = await connect({ nc.close(); ``` {% endtab %} +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; +const char *servers[] = {"nats://127.0.0.1:1222", "nats://127.0.0.1:1223", "nats://127.0.0.1:1224"}; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetServers(opts, servers, 3); +if (s == NATS_OK) + s = natsOptions_SetNoRandomize(opts, true); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/reconnect/wait.md b/developing-with-nats/reconnect/wait.md index 50d84dd..49b1c46 100644 --- a/developing-with-nats/reconnect/wait.md +++ b/developing-with-nats/reconnect/wait.md @@ -76,5 +76,26 @@ let nc = await connect({ nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + // Set reconnect interval to 10 seconds (10,000 milliseconds) + s = natsOptions_SetReconnectWait(opts, 10000); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/security/creds.md b/developing-with-nats/security/creds.md index 47cf305..7406315 100644 --- a/developing-with-nats/security/creds.md +++ b/developing-with-nats/security/creds.md @@ -88,5 +88,28 @@ let nc = await connect({ }); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + // Pass the credential file this way if the file contains both user JWT and seed. + // Otherwise, if the content is split, the first file is the user JWT, the second + // contains the seed. + s = natsOptions_SetUserCredentialsFromFiles(opts, "path_to_creds_file", NULL); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/security/nkey.md b/developing-with-nats/security/nkey.md index d49d2b7..d2b79bb 100644 --- a/developing-with-nats/security/nkey.md +++ b/developing-with-nats/security/nkey.md @@ -105,5 +105,45 @@ let nc = await connect({ }); ``` {% endtab %} + +{% tab title="C" %} +```c +static natsStatus +sigHandler( + char **customErrTxt, + unsigned char **signature, + int *signatureLength, + const char *nonce, + void *closure) +{ + // Sign the given `nonce` and return the signature as `signature`. + // This needs to allocate memory. The length of the signature is + // returned as `signatureLength`. + // If an error occurs the user can return specific error text through + // `customErrTxt`. The library will free this pointer. + + return NATS_OK; +} + +(...) + +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; +const char *pubKey = "my public key......"; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetNKey(opts, pubKey, sigHandler, NULL); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/security/tls.md b/developing-with-nats/security/tls.md index d9b1533..c6392ae 100644 --- a/developing-with-nats/security/tls.md +++ b/developing-with-nats/security/tls.md @@ -203,6 +203,28 @@ let nc = await connect({ }); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetCertificatesChain(opts, "client-cert.pem", "client-key.pem"); +if (s == NATS_OK) + s = natsOptions_SetCATrustedCertificates(opts, "rootCA.pem"); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} ## Connecting with the TLS Protocol diff --git a/developing-with-nats/security/token.md b/developing-with-nats/security/token.md index f7fe283..54048c9 100644 --- a/developing-with-nats/security/token.md +++ b/developing-with-nats/security/token.md @@ -69,6 +69,26 @@ end let nc = await connect({url: server.nats, token: "mytoken"}); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetToken(opts, "mytoken"); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} ## Connecting with a Token in the URL @@ -134,5 +154,25 @@ let url = `nats://:mytoken@127.0.0.1:${port}`; let nc = await connect({url: url}); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetURL(opts, "nats://mytoken@127.0.0.1:4222"); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/security/userpass.md b/developing-with-nats/security/userpass.md index 755a043..a36789b 100644 --- a/developing-with-nats/security/userpass.md +++ b/developing-with-nats/security/userpass.md @@ -93,6 +93,26 @@ end let nc = await connect({url: server.nats, user: "myname", pass: "password"}); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetUserInfo(opts, "myname", "password"); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} ## Connecting with a User/Password in the URL @@ -172,5 +192,25 @@ let url = `nats://myname:password@127.0.0.1:${port}`; let nc = await connect({url: url}); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsOptions *opts = NULL; +natsStatus s = NATS_OK; + +s = natsOptions_Create(&opts); +if (s == NATS_OK) + s = natsOptions_SetURL(opts, "nats://myname:password@127.0.0.1:4222"); +if (s == NATS_OK) + s = natsConnection_Connect(&conn, opts); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +natsOptions_Destroy(opts); +``` +{% endtab %} {% endtabs %} diff --git a/developing-with-nats/sending/caches.md b/developing-with-nats/sending/caches.md index 57a2ac8..bc82ad5 100644 --- a/developing-with-nats/sending/caches.md +++ b/developing-with-nats/sending/caches.md @@ -109,6 +109,29 @@ await nc.flush(); nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsStatus s = NATS_OK; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); + +// Send a request and wait for up to 1 second +if (s == NATS_OK) + s = natsConnection_PublishString(conn, "foo", "All is Well"); + +// Sends a PING and wait for a PONG from the server, up to the given timeout. +// This gives guarantee that the server has processed the above message. +if (s == NATS_OK) + s = natsConnection_FlushTimeout(conn, 1000); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} ## Flush and Ping/Pong diff --git a/developing-with-nats/sending/replyto.md b/developing-with-nats/sending/replyto.md index 526c91a..e891053 100644 --- a/developing-with-nats/sending/replyto.md +++ b/developing-with-nats/sending/replyto.md @@ -155,5 +155,23 @@ await nc.subscribe(inbox, (err, msg) => { nc.publish('time', "", inbox); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsStatus s = NATS_OK; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); +// Publish a message and provide a reply subject +if (s == NATS_OK) + s = natsConnection_PublishRequestString(conn, "request", "reply", "this is the request"); + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +``` +{% endtab %} + {% endtabs %} diff --git a/developing-with-nats/sending/request_reply.md b/developing-with-nats/sending/request_reply.md index d1060ad..c64cffa 100644 --- a/developing-with-nats/sending/request_reply.md +++ b/developing-with-nats/sending/request_reply.md @@ -110,6 +110,36 @@ t.log('the time is', msg.data); nc.close(); ``` {% endtab %} + +{% tab title="C" %} +```c +natsConnection *conn = NULL; +natsMsg *msg = NULL; +natsStatus s = NATS_OK; + +s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL); + +// Send a request and wait for up to 1 second +if (s == NATS_OK) + s = natsConnection_RequestString(&msg, conn, "request", "this is the request", 1000); + +if (s == NATS_OK) +{ + printf("Received msg: %s - %.*s\n", + natsMsg_GetSubject(msg), + natsMsg_GetDataLength(msg), + natsMsg_GetData(msg)); + + // Destroy the message that was received + natsMsg_Destroy(msg); +} + +(...) + +// Destroy objects that were created +natsConnection_Destroy(conn); +``` +{% endtab %} {% endtabs %} You can think of request-reply in the library as a subscribe, get one message, unsubscribe pattern. In Go this might look something like: diff --git a/developing-with-nats/sending/structure.md b/developing-with-nats/sending/structure.md index eb49c70..eadc80e 100644 --- a/developing-with-nats/sending/structure.md +++ b/developing-with-nats/sending/structure.md @@ -106,5 +106,11 @@ let nc = await connect({ nc.publish('updates', {ticker: 'GOOG', price: 1200}); ``` {% endtab %} + +{% tab title="C" %} +```c +// Structured data is not configurable in C NATS Client. +``` +{% endtab %} {% endtabs %}