nanomsg
Home Download Documentation Development Community Support
Getting Started with 'nanomsg'
This document is derived from an original post by Tim Dysinger. That post is no longer available, but we have modified and restructured it, as well as making enhancments and corrections. Tim’s original code is on github, but we recommend using the examples here as they have a number of corrections.
If you want to use the experimental nng library instead, see the document Getting Started with 'nng'.

Survey (Everybody Votes)

Everybody Votes

The surveyor pattern is used to send a timed survey out, responses are individually returned until the survey has expired. This pattern is useful for service discovery and voting algorithms.

survey.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <nanomsg/nn.h>
#include <nanomsg/survey.h>

#define SERVER "server"
#define CLIENT "client"
#define DATE   "DATE"

void
fatal(const char *func)
{
        fprintf(stderr, "%s: %s\n", func, nn_strerror(nn_errno()));
        exit(1);
}

char *
date(void)
{
        time_t now = time(&now);
        struct tm *info = localtime(&now);
        char *text = asctime(info);
        text[strlen(text)-1] = '\0'; // remove '\n'
        return (text);
}

int
server(const char *url)
{
        int sock;

        if ((sock = nn_socket (AF_SP, NN_SURVEYOR)) < 0) {
                fatal("nn_socket");
        }
        if (nn_bind(sock, url)  < 0) {
                fatal("nn_bind");
        }
        for (;;) {
                printf("SERVER: SENDING DATE SURVEY REQUEST\n");
                int bytes = nn_send(sock, DATE, strlen(DATE) + 1, 0);
                if (bytes < 0) {
                        fatal("nn_send");
                }

                for (;;) {
                        char *buf = NULL;
                        int bytes = nn_recv(sock, &buf, NN_MSG, 0);
                        if (bytes < 0) {
                                if (nn_errno() == ETIMEDOUT) {
                                        break;
                                }
                                fatal("nn_recv");
                        }
                        printf("SERVER: RECEIVED \"%s\" SURVEY RESPONSE\n",
                            buf); (1)
                        nn_freemsg(buf);
                }

                printf("SERVER: SURVEY COMPLETE\n");
                sleep(1); // Start another survey in a second
        }
}

int
client(const char *url, const char *name)
{
        int sock;

        if ((sock = nn_socket(AF_SP, NN_RESPONDENT)) < 0) {
                fatal("nn_socket");
        }
        if (nn_connect (sock, url) < 0) {
                fatal("nn_connect");
        }
            for (;;) {
                char *buf = NULL;
                int bytes = nn_recv(sock, &buf, NN_MSG, 0);
                if (bytes >= 0) {
                        printf("CLIENT (%s): RECEIVED \"%s\" SURVEY REQUEST\n",
                            name, buf); (1)
                        nn_freemsg(buf);
                        char *d = date();
                        int sz_d = strlen(d) + 1; // '\0' too
                        printf("CLIENT (%s): SENDING DATE SURVEY RESPONSE\n",
                           name);
                        if (nn_send(sock, d, sz_d, 0) < 0) {
                                fatal("nn_send");
                        }
                }
        }
}

int
main(const int argc, const char **argv)
{
        if ((argc >= 2) && (strcmp(SERVER, argv[1]) == 0))
                return (server(argv[2]));

        if ((argc >= 3) && (strcmp(CLIENT, argv[1]) == 0))
                return (client(argv[2], argv[3]));

        fprintf(stderr, "Usage: survey %s|%s <URL> <ARG> ...\n",
            SERVER, CLIENT);
        return 1;
}
1 Blithely assumes message is ASCIIZ string. Real code should check it.
Compilation
gcc survey.c -lnanomosg -o survey
Execution
./survey server ipc:///tmp/survey.ipc & server=$!
./survey client ipc:///tmp/survey.ipc client0 & client0=$!
./survey client ipc:///tmp/survey.ipc client1 & client1=$!
./survey client ipc:///tmp/survey.ipc client2 & client2=$!
sleep 4 (1)
kill $server $client0 $client1 $client2
1 The first survey times out with no responders because the clients aren’t started yet.
Output
SERVER: SENDING DATE SURVEY REQUEST
SERVER: SURVEY COMPLETE
SERVER: SENDING DATE SURVEY REQUEST
CLIENT (client2): RECEIVED "DATE" SURVEY REQUEST
CLIENT (client1): RECEIVED "DATE" SURVEY REQUEST
CLIENT (client0): RECEIVED "DATE" SURVEY REQUEST
CLIENT (client1): SENDING DATE SURVEY RESPONSE
CLIENT (client0): SENDING DATE SURVEY RESPONSE
CLIENT (client2): SENDING DATE SURVEY RESPONSE
SERVER: RECEIVED "Mon Jan  8 13:10:43 2018" SURVEY RESPONSE
SERVER: RECEIVED "Mon Jan  8 13:10:43 2018" SURVEY RESPONSE
SERVER: RECEIVED "Mon Jan  8 13:10:43 2018" SURVEY RESPONSE
SERVER: SURVEY COMPLETE
"nanomsg" is a trademark of Garrett D'Amore.