How to allow request coming from specific IP address only in 0MQ request-reply pattern.
I don't want to receive request from any other IP address. I want to communicate only between two IP address first one is request maker and second one is reply maker.
request.c
#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main(void) {
void *context = zmq_ctx_new();
void *requester = zmq_socket(context, ZMQ_REQ);
zmq_connect(requester, "tcp://127.0.0.1:5555");
char buffer[10];
printf ("Sending Hello\n");
zmq_send(requester, "Hello", 5, 0);
zmq_recv(requester, buffer, 10, 0);
printf("Received: %s\n", buffer);
zmq_close (requester);
zmq_ctx_destroy (context);
return 0;
}
reply.c
#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
int main(void) {
void *context = zmq_ctx_new();
void *responder = zmq_socket(context, ZMQ_REP);
int rc = zmq_bind(responder, "tcp://127.0.0.1:5555");
assert(rc == 0);
char buffer[10];
zmq_recv(responder, buffer, 10, 0);
printf("Recived: %s\n", buffer);
sleep(1);
zmq_send(responder, "World", 5, 0);
return 0;
}
From comments:
From stackoverflow.com/questions/20336954/0mq-get-message-ip it is
impossible. Do not use 0MQ and use other tool.
Related
Can someone show me "Hello World" example for zeromq pub/sub in c using libzmq. I have done coding req/rep example It's well documented but I couldn't find good hello world example for pub/sub that works fine with me.
Here is my try.
pub.c
#include <zmq.h>
#include <string.h>
int main()
{
void *context = zmq_ctx_new();
void *publisher = zmq_socket(context, ZMQ_PUB);
zmq_bind(publisher, "tcp://127.0.0.1:5555");
char message[15] = "Hello World!";
while(1)
{
zmq_msg_t msg;
zmq_msg_init_size(&message, strlen(message));
memcpy(zmq_msg_data(&msg), message, strlen(message));
zmq_msg_send(publisher, &msg, 0);
zmq_msg_close(&msg);
}
zmq_close(publisher);
zmq_ctx_destroy(context);
return 0;
}
sub.c
#include <zmq.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main()
{
void *context = zmq_ctx_new();
void *subscriber = zmq_socket(context, ZMQ_SUB);
int rc = zmq_connect(subscriber, "tcp://127.0.0.1:5555");
assert(rc == 0);
zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0);
char message[15] = "";
while(1)
{
zmq_msg_t msg;
zmq_msg_init(&msg);
zmq_msg_recv(subscriber, &msg, 0);
int size = zmq_msg_size(&msg);
memcpy(message, zmq_msg_data(&msg), size);
zmq_msg_close(&msg);
printf("%s\n", message);
}
zmq_close(subscriber);
zmq_ctx_destroy(context);
return 0;
}
Thanks in advance
Finally this code works with me
pub.c
#include <stdio.h>
#include <assert.h>
#include <zmq.h>
int main()
{
void *context = zmq_ctx_new();
void *publisher = zmq_socket(context, ZMQ_PUB);
int rc = zmq_bind(publisher, "tcp://127.0.0.1:5556");
assert(rc == 0);
while(1)
{
rc = zmq_send(publisher, "Hello World!", 12, 0);
assert(rc == 12);
}
zmq_close(publisher);
zmq_ctx_destroy(context);
return 0;
}
sub.c
#include <stdio.h>
#include <assert.h>
#include <zmq.h>
int main()
{
void *context = zmq_ctx_new();
void *subscriber = zmq_socket(context, ZMQ_SUB);
int rc = zmq_connect(subscriber, "tcp://127.0.0.1:5556");
assert(rc == 0);
rc = zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0);
assert(rc == 0);
char message[12];
while(1)
{
rc = zmq_recv(subscriber, message, 12, 0);
assert(rc != -1);
printf("%s\n", message);
}
zmq_close(subscriber);
zmq_ctx_destroy(context);
return 0;
}
I have a table with 2 entry :
id hostname ip port
1 Raspberry pi 192.168.1.49 22
2 Test 127.0.0.1 22
In my code i get only the first entry with sqlite3.
I have :
{"id": "1", "hostname": "Raspberry pi", "ip": "192.168.1.49", "port": "22"}
Where is the second entry ?
I tried with printf and get the same problem it's not json issue.
There is the code :
#include <stdarg.h> /* va_list */
#include <stddef.h> /* NULL */
#include <stdint.h> /* int64_t */
#include <stdlib.h>
#include <string.h> /* memset */
#include <stdio.h>
#include <sqlite3.h>
#include <kcgi.h>
#include <kcgihtml.h>
#include <kcgijson.h>
static int callback(void *ptr, int argc, char **argv, char **azColName) {
struct kjsonreq *req = (struct kjsonreq *)ptr;
struct khtmlreq r;
int i;
for(i=0; i<argc; i++){
kjson_putstringp(req, azColName[i], argv[i] ? argv[i] : "NULL");
}
}
int
main(void)
{
struct kreq r;
struct kjsonreq req;
const char *page = "index";
if (khttp_parse(&r, NULL, 0, &page, 1, 0) != KCGI_OK)
return EXIT_FAILURE;
khttp_head(&r, kresps[KRESP_STATUS],
"%s", khttps[KHTTP_200]);
khttp_head(&r, kresps[KRESP_CONTENT_TYPE],
"%s", kmimetypes[r.mime]);
khttp_body(&r);
kjson_open(&req, &r);
kjson_obj_open(&req);
sqlite3 *db;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("/var/www/MaSSH/databases/massh.db", &db);
if(rc){
sqlite3_close(db);
}
rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback, &req, &zErrMsg);
if(rc!= SQLITE_OK){
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
kjson_obj_close(&req);
kjson_close(&req);
khttp_free(&r);
return EXIT_SUCCESS;
}
#include <sys/types.h> /* size_t, ssize_t */
#include <stdarg.h> /* va_list */
#include <stddef.h> /* NULL */
#include <stdint.h> /* int64_t */
#include <stdlib.h>
#include <string.h> /* memset */
#include <stdio.h>
#include <sqlite3.h>
#include <kcgi.h>
#include <kcgihtml.h>
#include <kcgijson.h>
int
main(void)
{
struct kreq r;
struct kjsonreq req;
const char *page = "index";
if (khttp_parse(&r, NULL, 0, &page, 1, 0) != KCGI_OK)
return EXIT_FAILURE;
khttp_head(&r, kresps[KRESP_STATUS],
"%s", khttps[KHTTP_200]);
khttp_head(&r, kresps[KRESP_CONTENT_TYPE],
"%s", kmimetypes[r.mime]);
khttp_body(&r);
kjson_open(&req, &r);
kjson_obj_open(&req);
sqlite3 *db;
sqlite3_stmt *res;
int rc;
rc = sqlite3_open("/var/www/MaSSH/databases/massh.db", &db);
if(rc){
sqlite3_close(db);
}
rc = sqlite3_prepare_v2(db, "SELECT * FROM hosts;", -1, &res, 0);
while((rc = sqlite3_step(res)) == SQLITE_ROW){
kjson_objp_open(&req, "host");
kjson_putstringp(&req, "id", sqlite3_column_text(res,0));
kjson_putstringp(&req, "hostname", sqlite3_column_text(res,1));
kjson_putstringp(&req, "ip", sqlite3_column_text(res,2));
kjson_putstringp(&req, "port", sqlite3_column_text(res,3));
kjson_obj_close(&req);
}
sqlite3_close(db);
kjson_obj_close(&req);
kjson_close(&req);
khttp_free(&r);
return EXIT_SUCCESS;
}
I'm writing a Memcached UDP client with libmemcached/memcached.h to send some arbitrary loads on Memcached server. I can send set requests in UDP but I'm unable to send get requests, here is the snippet I wrote for this!
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <libmemcached/memcached.h>
#include <time.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
int main(int argc, char *argv[])
{
memcached_server_st *servers = NULL;
memcached_st *memc;
memcached_return rc;
char * res;
char *key= "kay";
int size = 1000;
char * value = malloc(size);
uint32_t flags;
size_t return_value_length;
char * ip = argv[2];
memset(value, 1, size);
memc = memcached_create(NULL);
servers= memcached_server_list_append(servers, ip, 11211, &rc);
rc = memcached_server_push(memc, servers);
memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, (uint64_t)1);
rc = memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0);
if (rc == MEMCACHED_SUCCESS)
fprintf(stderr,"Key stored successfully\n");
else
fprintf(stderr,"Couldn't store key: %s\n",memcached_strerror(memc, rc));
while ( true)
{
res = memcached_get(memc, key, strlen(key), &return_value_length, &flags, &rc);
free(res);
if(rc != MEMCACHED_SUCCESS)
{
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
}
}
memcached_free(memc);
return 0;
Actually, get requests always are unsuccessful!!! I also monitored the packets with Wireshark the client doesn't even send any packet out to the server!!! And it just got failed while sending get request.
Is there any obvious problem in the code which I couldn't see?
Thank you
According to the manpage of memcached_behaviour_set():
The following operations will return MEMCACHED_NOT_SUPPORTED when
executed with the MEMCACHED_BEHAVIOR_USE_UDP enabled:
memcached_version(), memcached_stat(), memcached_get(),
memcached_get_by_key(), memcached_mget(), memcached_mget_by_key(),
memcached_fetch(), memcached_fetch_result(),
memcached_fetch_execute().
So indeed, memcached_get() does not work when the memcached-handle is set to UDP transport. You will have to use TCP for that.
I have a basic server-client program that I'm writing in C and I am stuck with an issue regarding strings and concatenation.
Basically I have some strings (in the example below just 2) that I have to put into a buffer which size is determined by:
total # of registered people * 33
Both the strings in the example have a length which is much less than the length of the buffer. I want to obtain something like this after the concatenation:
[0] [32]
people_list=Mark Amy\0;
where Mark(which is inserted secondly) is right at the start of the buffer (people_list) and Amy is 32 characters away from the start of Mark (I hope I've made myself clear).
This is because the client code was given to me and I cannot modify it. The client code takes the buffer and reads the first element, then jumps of 32 chars and reads again.
The output I get from the printf of the client is this:
connected to server
Registered people:
Mark
while I'd like this:
connected to server
Registered people:
Mark
Amy
The communication is implemented through sockets, which I have already checked, but if you wish to suggest some changes I would appreciate that.
Server code:
#include <stdio.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#define LENGTH 32
struct person {
char name[LENGTH+1];
struct person *next;
struct person *prev;
};
struct person *p_head = NULL;
void addPerson(char* name_p){
struct person *new = (struct person*) malloc(sizeof(struct person));
strcpy(new->name, name_p);
new->name[LENGTH]='\0';
new->next=p_head;
new->prev=NULL;
p_head=new;
}
int main(){
int fd_ser;
int fd_c;
int N=100;
char buf[N];
int times=0;
char* path="tmp/sock";
struct sockaddr_un sa;
unlink(path);
sa.sun_family=AF_UNIX;
strncpy(sa.sun_path,(char*) path, sizeof(sa.sun_path));
if((fd_ser=socket(AF_UNIX,SOCK_STREAM,0))<0){ //socket
perror((const char*) (size_t) errno);
exit(EXIT_FAILURE);
}
if ( bind(fd_ser,(struct sockaddr *)&sa, sizeof(sa))<0){
perror("bind\n");
}
listen(fd_ser,10); //listen
struct sockaddr_un addr;
int addr_size= sizeof(struct sockaddr_un);
fd_c=0;
while( (fd_c=accept(fd_ser,(struct sockaddr*) &addr, (socklen_t*)&addr_size))<0){
printf("waiting for connections...\n");
sleep(2);
}
//initialize list of people
char* Amy="Amy";
char* Mark="Mark";
addPerson(Amy);
addPerson(Mark);
//now concat the name strings in a buffer to be sent to the client
char* people_list;
unsigned int list_len;
int value;
struct person* ptr=(struct person*) malloc(sizeof(struct person));
ptr=p_head;
int offset=0;
int i=0;
while(ptr!=NULL){
i++;
people_list=realloc(people_list,i*LENGTH); //every single name has to be LENGTH characters
strcpy(&people_list[offset],ptr->name);
ptr=ptr->next;
offset=offset+LENGTH;
}
people_list[i*LENGTH]='\0';
list_len=(i*LENGTH)+1;
value=write(fd_c, &(list_len), sizeof(unsigned int));
if(value==-1){
perror("write length");
return -1;
}
int toWrite=list_len;
char *toRead=people_list;
while(toWrite>0){
value=write(fd_c, toRead, toWrite);
if(value==-1){
perror("write data");
return -1;
}
toWrite=toWrite-value;
toRead=toRead+value;
if(toRead<=people_list + list_len) break;
}
close(fd_c);
close(fd_ser);
return 0;
}
Client code:
#include <stdio.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <assert.h>
#include <errno.h>
#define MAX_LENGTH 2048
#define LENGTH 32
int main(){
int fd_cli;
char* path="tmp/sock";
struct sockaddr_un sa;
sa.sun_family=AF_UNIX;
strncpy(sa.sun_path,(char*) path, sizeof(sa.sun_path));
if( (fd_cli = socket(AF_UNIX, SOCK_STREAM, 0))==-1){
perror((const char*) (size_t) errno);
return -1;
}
while( (connect(fd_cli,(struct sockaddr*)&sa, sizeof(struct sockaddr_un))) == -1 ) {
if ( errno == ENOENT ) { sleep(1); }
else perror("connect:");
errno=0;
sleep(1);
}
printf("connected to server\n");
int value;
unsigned int len_data;
value=read(fd_cli,&(len_data),sizeof(unsigned int));
if(value==-1){
perror("read length");
return -1;
}
char* buffer=malloc(len_data*sizeof(char));
int toRead=len_data;
char *toWrite=buffer;
while(toRead>0){
value=read(fd_cli, toWrite, toRead);
if(value==-1){
perror("read buffer");
return -1;
}
toRead=toRead-value;
toWrite=toWrite+value;
if(toWrite<=buffer + len_data) break;
}
int people_n = len_data / (LENGTH+1);
assert(people_n > 0); //proceeds only if there is at least one person registered
printf("Registered people:\n");
for(int i=0,p=0;i<people_n; ++i, p+=(LENGTH+1)) {
printf(" %s\n", &buffer[p]);
}
close(fd_cli);
return 0;
}
I really hope I've explained the problem clearly! Thank you for your help!
It's printing only the first user (Mark) because of this line:
int people_n = len_data / (LENGTH+1);
In this example, len_data = 65, LENGTH = 32. So when you are adding 1 to LENGTH, it will return 1 (65/33 = 1.96 => you get 1). Then it only prints the first user.
Consider using Valgrind. It will help you checking the use of the memory.
I am learning zeromq and have the following test code:
void *context = (void *)zmq_ctx_new();
if (context == NULL) {
printf("context is null\n");
} else {
printf("context was created successfully\n");
}
printf("connecting to the 0mq server\n");
void *responder = zmq_socket (context, ZMQ_REQ);
printf("got socket\n");
if (responder == NULL) {
printf("responder is null\n");
} else {
printf("responder was created successfully\n");
}
When I run the code, it crashes when the zmq_socket() is called. Here is the output:
Starting 0mq server context was created successfully connecting to the
0mq server Segmentation fault (core dumped)
I'm not sure why zmq_socket() fails. I have tried to move the zmq library in the beginning of the linking series in my Makefile. It still fails.
Any help would be highly appreciated.
change
void context = (void)zmq_ctx_new();
into
void *context = (void *)zmq_ctx_new();
And, as I tried your code, void context = (void) zmq_ctx_new() would cause compile error.
here is my code which can work on my OSX.
gcc -o cli client.c -lzmq
gcc -o srv server.c -lzmq
client.c:
#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main (void)
{
printf ("Connecting to hello world server…\n");
void *context = (void *)zmq_ctx_new ();
void *requester = zmq_socket (context, ZMQ_REQ);
zmq_connect (requester, "tcp://localhost:5555");
int request_nbr;
for (request_nbr = 0; request_nbr != 10; request_nbr++) {
char buffer [10];
char snd[] = "hello";
printf ("Sending Hello %d…\n", request_nbr);
zmq_send (requester, snd, sizeof(snd), 0);
zmq_recv (requester, buffer, 10, 0);
printf ("Received World %d\n", request_nbr);
}
zmq_close (requester);
zmq_ctx_destroy (context);
return 0;
}
server.c:
#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main (void)
{
// Socket to talk to clients
void *context = zmq_ctx_new ();
void *responder = zmq_socket (context, ZMQ_REP);
int rc = zmq_bind (responder, "tcp://*:5555");
assert (rc == 0);
while (1) {
int nrecv;
char buffer [10];
nrecv = zmq_recv (responder, buffer, 10, 0);
printf ("[%d] Received %s\n", nrecv, buffer);
sleep (1); // Do some 'work'
zmq_send (responder, "World", 5, 0);
}
return 0;
}