PubSub and survey of NANOMSG Communication library

Source: Internet
Author: User
Tags bind current time sleep socket strlen

NANOMSG Experiment--pubsub

The Publish subscription model is a common feature provided by many message middleware. The message mechanism enables the message publisher and the message to receive (consume) people
To decouple. PubSub mode is also one of the message models directly supported by NANOMSG, so through the PubSub model experiment,
At the same time, we also have a general understanding of the basic usage of nanomsg.

Service Side

The code is as follows Copy Code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <nanomsg/nn.h>
#include <nanomsg/pubsub.h>

void usage (const char *name)
{
fprintf (stderr, "%s [Bind Url]n", name);
}

int main (int argc, char **argv)
{
if (argc!= 2) {
Usage (argv[0]);
Exit (-1);
}

const char *url = argv[1];
int sock = Nn_socket (af_sp, nn_pub);
if (sock < 0) {
fprintf (stderr, "Nn_socket failed:%sn", Nn_strerror (errno));
Exit (-1);
}

if (Nn_bind (sock, URL) < 0) {
fprintf (stderr, "Nn_bind failed:%sn", Nn_strerror (errno));
Exit (-1);
}

while (1) {
time_t Rawtime;
struct TM * TIMEINFO;

Time (&rawtime);
Timeinfo = LocalTime (&rawtime);
Char *text = asctime (Timeinfo);
int Textlen = strlen (text);
Text[textlen-1] = ';

printf ("Server:publishing DATE%sn", text);
Nn_send (sock, text, Textlen, 0);
Sleep (1);
}

return 0;
}



Nanomsg is very simple to use, as long as the direct include nanomsg/nn.h, you can use the basic API. Using the built-in communication mode,
need to introduce corresponding header files, such as PubSub mode, the introduction of Nonomsg/pubsub.h can be.

PubSub server, you need to first create a socket through a nn_socket call, which mimics the POSIX interface,
function returns a file descriptor. Therefore, you can determine whether or not to create a success directly by judging whether the return value is greater than 0. Note that the second parameter is a protocol,
The corresponding macros are defined in the protocol-related header file. All operations are then based on this file descriptor.
Like Berkeley sockets, the server needs to bind a port, nanomsg need to bind a URL. The formats currently supported by NANOMSG are:
* In-process communication (INPROC): URL format is inproc://test
* Inter-process (IPC): URL format is IPC:///TMP/TEST.IPC
* TCP communication: URL format is tcp://*:5555

GitHub on the source seems to have supported WebSocket.

The nanomsg error is the same as UNIX, and the errno is set after the failure, and the corresponding error text can be obtained by Nn_strerror.

After the bind is over, you can send a message to the socket via the Nn_send function. This function parameter is similar to the Berkeley Sockets API interface.
The current time is directly obtained here and then sent to all subscribers.

Client

The code is as follows Copy Code
#include <stdio.h>
#include <stdlib.h>

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

int main (int argc, char **argv)
{
if (argc!= 3) {
fprintf (stderr, "Usage:%s NAME bind_urln", argv[0]);
Exit (-1);
}
const char *name = argv[1];
const char *url = argv[2];

int sock = Nn_socket (af_sp, nn_sub);
if (sock < 0) {
fprintf (stderr, "fail to create socket:%SN", Nn_strerror (errno));
Exit (-1);
}
if (nn_setsockopt (sock, Nn_sub, Nn_sub_subscribe, "", 0) < 0) {
fprintf (stderr, "fail to set Sorket opts:%sn", Nn_strerror (errno));
Exit (-1);
}

if (Nn_connect (sock, URL) < 0) {
fprintf (stderr, "fail to connect to%s:%sn", URL, Nn_strerror (errno));
Exit (-1);
}


while (1) {
char *buf = NULL;
int bytes = NN_RECV (sock, &buf, nn_msg, 0);
printf ("CLIENT (%s): RECEIVED%sn", name, BUF);
Nn_freemsg (BUF);
}

Nn_shutdown (sock, 0);

return 0;
}




Client initialization is similar to the service side, and the current socket needs to be set to a message subscriber through nn_setsockopt before the server is connected. The
then connects the publisher through the Nn_connect, with the same parameters as the service-side bind, and also a socket, a URL.
The URL here is the same as the URL of the service-side bind. After that, a dead loop is constantly receiving messages from the publisher. The

test

is compiled first, the same as normal C programs, and only adds link nanomsg.

Gcc-o pubserver pubserver.c-lnanomsg
gcc-o pubclient pubclient.c-lnanomsg


To facilitate testing, write a simple sh Ell script:
   

  code is as follows copy code
#!/bin/bash

base= "$ (CD" $ (dirname "$") "&& pwd"
PU b= $BASE/pubserver
sub= $BASE/pubclient

url= "tcp://127.0.0.1:1234"

Echo "Start Pubserver to bind TCP : $URL

$PUB tcp://127.0.0.1:1234 &

Echo ' start to start pubclient '
for ((i = 0; I < i++)
    do
    echo "Start client$i"
    $SUB client$i $URL &amp
    sleep 1
Done

Sleep
Echo, kill all process and exit

for-pid in ' jobs-p '
do
    echo Kill $pi D "
    kill $pid
Done

Wait




The script is simple, start a message publisher first, and then start a message recipient per second. After waiting for 20s, kill all child processes.

The output of the script:

The code is as follows Copy Code
Start Pubserver to bind tcp:tcp://127.0.0.1:1234
Start to start pubclient
Start client0
Server:publishing DATE Tue Feb 17 15:12:11 2015
Start CLIENT1
Server:publishing DATE Tue Feb 17 15:12:12 2015
CLIENT (client0): RECEIVED Tue Feb 17 15:12:12 2015
CLIENT (CLIENT1): RECEIVED Tue Feb 17 15:12:12 2015
Start Client2
Server:publishing DATE Tue Feb 17 15:12:13 2015
CLIENT (client0): RECEIVED Tue Feb 17 15:12:13 2015
CLIENT (CLIENT1): RECEIVED Tue Feb 17 15:12:13 2015
CLIENT (CLIENT2): RECEIVED Tue Feb 17 15:12:13 2015
Start Client3
Server:publishing DATE Tue Feb 17 15:12:14 2015
CLIENT (client0): RECEIVED Tue Feb 17 15:12:14 2015
CLIENT (CLIENT1): RECEIVED Tue Feb 17 15:12:14 2015
CLIENT (CLIENT2): RECEIVED Tue Feb 17 15:12:14 2015
...
Server:publishing DATE Tue Feb 17 15:12:41 2015
CLIENT (client0): RECEIVED Tue Feb 17 15:12:41 2015
CLIENT (CLIENT1): RECEIVED Tue Feb 17 15:12:41 2015
CLIENT (CLIENT2): RECEIVED Tue Feb 17 15:12:41 2015
CLIENT (CLIENT3): RECEIVED Tue Feb 17 15:12:41 2015
CLIENT (CLIENT4): RECEIVED Tue Feb 17 15:12:41 2015
CLIENT (CLIENT5): RECEIVED Tue Feb 17 15:12:41 2015
CLIENT (CLIENT6): RECEIVED Tue Feb 17 15:12:41 2015
CLIENT (client7): RECEIVED Tue Feb 17 15:12:41 2015
CLIENT (client8): RECEIVED Tue Feb 17 15:12:41 2015
CLIENT (CLIENT9): RECEIVED Tue Feb 17 15:12:41 2015
Kill all process and exit




You can see that each time a new subscriber is started, each Subscriber can receive the current time of the publisher's publication.


nanomsg Experiment--survey

The survey mode is a pattern that is queried by the server, and the client responds to requests for replies. This pattern is very useful in distributed systems,
Can be used to do service discovery, distributed things and other distributed queries.
Client

The client implementation is more convenient, in addition to the basic call (create socket, connection URL), is to receive the server query first
(in the case of simple, server-side inquiries are fixed, so there is no check on the content) to send a response to the query
(In the example, the current time of the Send server)

The code is as follows Copy Code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <nanomsg/nn.h>
#include <nanomsg/survey.h>

using namespace Std;

int main (int argc, const char **argv) {
if (argc!= 3) {
fprintf (stderr, "Usage:%s NAME urln", argv[0]);
Exit (-1);
}
const char *name = argv[1];
const char *url = argv[2];

int sock = Nn_socket (af_sp, nn_respondent);
if (sock < 0) {
fprintf (stderr, "Nn_socket fail:%sn", Nn_strerror (errno));
Exit (-1);
}
if (Nn_connect (sock, URL) < 0) {
fprintf (stderr, "Nn_connect fail:%sn", Nn_strerror (errno));
Exit (-1);
}

while (1) {
char *buf = NULL;
int bytes = NN_RECV (sock, &buf, nn_msg, 0);

if (bytes > 0) {
printf ("CLIENT (%s): RECEIVED"%s "SURVEY requestn", name, BUF);
Nn_freemsg (BUF);

Char sendbuffer[128];
time_t Rawtime;
struct TM * TIMEINFO;

Time (&rawtime);
Timeinfo = LocalTime (&rawtime);
Char *timetext = asctime (Timeinfo);
int textlen = strlen (timetext);
Timetext[textlen-1] = ';
sprintf (Sendbuffer, "[%s]%s", name, timetext);
int sendsize = strlen (sendbuffer) + 1;
int actualsendsize = Nn_send (sock, Sendbuffer, sendsize, 0);

if (actualsendsize!= sendsize) {
fprintf (stderr, "nn_send fail, expect length%d, actual length%dn", Sendsize, actualsendsize);
Continue
}
}
}

Nn_shutdown (sock, 0);

return 0;
}




Once the message is received, it is simply printed and the response data is written to the server.

Service Side

There is a problem with the server, it is not normal to search for several examples before. After trying and simply looking at the code, it turns out that by nanomsg the underlying API,
Unable to get how many clients are currently present. However, if the response of all currently connected clients has been received, after calling Nn_recv again,
Returns 1 directly, indicating that the read failed, and that errno (obtained by the errno function) is set to EFSM, indicating that the current state machine is not in the correct state.

The code is as follows Copy Code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <nanomsg/nn.h>
#include <nanomsg/survey.h>

using namespace Std;

const char *survey_type = "DATE";

int main (int argc, char** argv)
{

if (argc!= 2) {
fprintf (stderr, "Usage:%s urln", argv[0]);
Exit (-1);
}
const char *url = argv[1];
int sock = Nn_socket (af_sp, Nn_surveyor);
if (sock < 0) {
fprintf (stderr, "Nn_socket failed:%sn", Nn_strerror (errno));
Exit (-1);
}

if (Nn_bind (sock, URL) < 0) {
fprintf (stderr, "Nn_bind fail:%sn", Nn_strerror (errno));
Exit (-1);
}

while (1) {
int sendsize = strlen (survey_type) + 1;
int actualsendsize;
printf ("Server:sending DATE SURVEY requestn");
if ((actualsendsize = Nn_send (sock, Survey_type, sendsize, 0))!= sendsize) {
fprintf (stderr, "nn_send fail, expect length%d, actual length%dn", Sendsize, actualsendsize);
Continue
}

int count = 0;
while (1) {
char *buf = NULL;
int bytes = NN_RECV (sock, &buf, nn_msg, 0);
if (bytes < 0 && nn_errno () = = etimedout) break;
if (bytes >= 0) {
printf ("server:received"%s "SURVEY Responsen", buf);
++count;
Nn_freemsg (BUF);
} else {
fprintf (stderr, "Nn_recv fail:%sn", Nn_strerror (errno));
Break
}
}
printf ("Server:current Receive%d survey RESPONSE.N", count);
Sleep (1);
}

Nn_shutdown (sock, 0);

return 0;

}




There are two dead loops here, and the outer loop is constantly trying to ask the client. After completing the query, read all the client responses through another dead loop,
Exits the loop when the read fails.

Before the source is found to directly determine whether the error is etimedout, after printing will find that each time there is no timeout, but the state machine error:

The code is as follows Copy Code
/* IF No survey is going in return EFSM error. */
if (Nn_slow (!nn_surveyor_inprogress (surveyor))
RETURN-EFSM;




Test

Testing is similar to the previous article, start a server, and then start the client again:

  code is as follows copy code
#!/bin/bash

base= "$ (CD" $ (dirname "$") "&& pwd"
SE rver= $BASE/surveyserver
client= $BASE/surveyclient

url= "tcp://127.0.0.1:1234"

Echo "Start Surveyserver to bind TCP: $URL
$SERVER tcp://127.0.0.1:1234 &

Echo ' start to start surveyclient '
for ((i = 0; I < i++))
do
    echo ' Start CLI Ent$i
    $CLIENT client$i $URL &amp
    sleep 1
do

Sleep 20
echo "Kill all process and exit"

for PID in ' jobs-p '
do
    echo "Kill $pid"
     kill $pid
Done

Wait




The output is:

The code is as follows Copy Code
Start Surveyserver to bind tcp:tcp://127.0.0.1:1234
Start to start surveyclient
Start client0
Server:sending DATE SURVEY REQUEST
Start CLIENT1
Nn_recv Fail:operation cannot be performed
Server:current Receive 0 survey response.
Start Client2
Server:sending DATE SURVEY REQUEST
CLIENT (client0): RECEIVED "DATE" SURVEY REQUEST
Server:received "[client0] Tue Feb 23:32:43 2015" SURVEY RESPONSE
CLIENT (CLIENT1): RECEIVED "DATE" SURVEY REQUEST
Server:received "[client1] Tue Feb 23:32:43 2015" SURVEY RESPONSE
Nn_recv Fail:operation cannot be performed
Server:current receive 2 survey response.
Start Client3
Server:sending DATE SURVEY REQUEST
CLIENT (client0): RECEIVED "DATE" SURVEY REQUEST
CLIENT (CLIENT1): RECEIVED "DATE" SURVEY REQUEST
CLIENT (CLIENT2): RECEIVED "DATE" SURVEY REQUEST
...
Server:sending DATE SURVEY REQUEST
CLIENT (client0): RECEIVED "DATE" SURVEY REQUEST
CLIENT (CLIENT1): RECEIVED "DATE" SURVEY REQUEST
CLIENT (CLIENT2): RECEIVED "DATE" SURVEY REQUEST
CLIENT (CLIENT3): RECEIVED "DATE" SURVEY REQUEST
CLIENT (CLIENT4): RECEIVED "DATE" SURVEY REQUEST
CLIENT (CLIENT5): RECEIVED "DATE" SURVEY REQUEST
CLIENT (CLIENT6): RECEIVED "DATE" SURVEY REQUEST
CLIENT (client7): RECEIVED "DATE" SURVEY REQUEST
CLIENT (CLIENT9): RECEIVED "DATE" SURVEY REQUEST
CLIENT (client8): RECEIVED "DATE" SURVEY REQUEST
Server:received "[client0] Tue Feb 23:33:09 2015" SURVEY RESPONSE
Server:received "[client1] Tue Feb 23:33:09 2015" SURVEY RESPONSE
Server:received "[Client2] Tue Feb 23:33:09 2015" SURVEY RESPONSE
Server:received "[Client3] Tue Feb 23:33:09 2015" SURVEY RESPONSE
Server:received "[Client4] Tue Feb 23:33:09 2015" SURVEY RESPONSE
Server:received "[client5] Tue Feb 23:33:09 2015" SURVEY RESPONSE
Server:received "[Client6] Tue Feb 23:33:09 2015" SURVEY RESPONSE
Server:received "[client7] Tue Feb 23:33:09 2015" SURVEY RESPONSE
Server:received "[Client9] Tue Feb 23:33:09 2015" SURVEY RESPONSE
Server:received "[client8] Tue Feb 23:33:09 2015" SURVEY RESPONSE
Nn_recv Fail:operation cannot be performed
Server:current Receive survey response.




You can see from the output that each time the last receive is completed, there will be a "Operation cannot be performed"
Error, which is EFSM error.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.