Curently I`m developing chat aplication using C and libevent library for both client and server. I started from simple prototype, where client simply send plain string, server recive it and send it to every connected user except the sender. But now I need to send not only the string, but also some information about the user, for example - his name. So, what the best wey to send complicated data (structs for exmaple) through sockets in C?
I have some code, that sends and recives structure as byte array, but i dont know, is it right to send it like that, or better to use JSON serialization for example. Thanks.
Client method, that read line and send it to server:
void *readmsg_and_send_msg(void *arg)
{
struct client *cl = (struct client *)arg;
struct sock_data data;
uint8_t sendbuff_array[DATA_BUFF_LENGTH];
data.type = SENDMSG_REQUEST;
char *line;
while (1)
{
line = getline();
if (line)
{
memcpy(data.data, (void *)line, strlen(line));
memcpy(sendbuff_array, &data, sizeof(data));
printf("%s\n", (char *)sendbuff_array);
bufferevent_write(cl->buf_ev, (void *)sendbuff_array, sizeof(sendbuff_array));
}
}
}
Server "on read" method:
void buffered_on_read(struct bufferevent *bev,
void *arg)
{
struct client *this_client = arg;
struct client *client;
sock_data_t *sockdata;
uint8_t data[DATA_BUFF_LENGTH];
size_t n;
/* Read 8k at a time and send it to all connected clients. */
for (;;)
{
n = bufferevent_read(bev, &data, sizeof(data));
//if 0 - end reading
if (n <= 0)
break;
}
sockdata = (sock_data_t *)data;
if (sockdata->type == SENDMSG_REQUEST)
{
printf("\033[0;36mNew message %s from %d recived\033[0m\n", (char *)sockdata->data, this_client->fd);
TAILQ_FOREACH(client, &client_tailq_head, entries)
{
if (client != this_client)
{
bufferevent_write(client->buf_ev, (void *)sockdata->data, sizeof(sockdata->data));
printf("Message %s successfully sended to user %d\n", (char *)sockdata->data, client->fd);
}
}
}
else
{
printf("%s - %d\n", (char *)sockdata->data, sockdata->type);
printf("Unimplemented request type\n");
return;
}
}
Struct, that I`m trying to send/recive:
#pragma pack(push, 1)
typedef struct sock_data_s
{
request_type_e type;
uint8_t data[DATA_BUFF_LENGTH];
} sock_data_t;
#pragma pack(pop)
Where request_type_e - enum, using for definding type on incoming request:
typedef enum request_type
{
REG_REQUEST = 0x0, //registration request
LOG_REQUEST, // login request
GETMSG_REQUEST, // get list of room`s messages request
SENDMSG_REQUEST, // send message to room
} request_type_e;
Related
Im trying to accomplish a udp socket data send and receive, where data will be send as small packets,
my function splits the data and send serially, then at receiver end, I combine them
my data input is like this
typedef struct SenderData {
unsigned short CommandCode;
int DataSize;
void *Data;
} SenderData;
my function goes like this
int send_packets(SenderData pkt_data,int pkt_size)
{
int data_size=0;
int no_cyc=0;
int rem_data=0;
int ndx=0;
int forloop_size=0;
int pending_size=0;
// find the size of data
data_size=pkt_data.DataSize;
if(data_size>pkt_size)
{
// find no of cycle required to send data
no_cyc=data_size/pkt_size;
// find remaining data
rem_data=data_size%pkt_size;
void *complete_data = pkt_data.Data;
void*data_out;
for(ndx=0;ndx<no_cyc;ndx++)
{
// store pkt size to data out;
memmove( data_out, (complete_data+(ndx*sizeof(int)*pkt_size)),pkt_size);
if (sendto(sd, data_out, pkt_size, 0,(struct sockaddr*)&groupSock,sizeof(groupSock)) < 0)
{
perror("sending datagram message");
}
}
forloop_size=no_cyc*pkt_size;
// remaining data size is
pending_size=forloop_size-rem_data;
// send remaining data
memmove( data_out,(complete_data+forloop_size), pending_size);
if (sendto(sd, data_out, pending_size, 0,(struct sockaddr*)&groupSock,sizeof(groupSock)) < 0)
{
perror("sending datagram message");
}
}
return 0;
}
data being send is
int cont[202];
SenderData data;
data.DataSize=sizeof(cont);
data.Data=&cont;
and my function call is like this
send_packets(data,100);
im doing the reverse of this function at receipt end
but when i run the code, it seams my data transfer has some issue, when i print the count array at the receipt end, im getting long numbers instead of data
I am trying to work with an API of one device, but it is using a WS interface with enforced Origin header, which is giving me troubles.
In Chrome, I can open the Console while a page with the correct Origin is loaded, create the WS connection, and send/receive messages without difficulties:
Note that sent messages (in green) are always acknowledged by the server.
For reference, this is what happens if I create the connection on a different page, which results in an Origin header mismatch, reported as 404:
To sidestep this problem, I turned to C, because the rest of my program is written in that anyway. This is the code I have right now, based mostly on this answer:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <libwebsockets.h>
#define KGRN "\033[0;32;32m"
#define KCYN "\033[0;36m"
#define KRED "\033[0;32;31m"
#define KYEL "\033[1;33m"
#define KBLU "\033[0;32;34m"
#define KCYN_L "\033[1;36m"
#define KBRN "\033[0;33m"
#define RESET "\033[0m"
static int destroy_flag = 0;
static int connection_flag = 0;
static int writeable_flag = 0;
static void INT_HANDLER(int signo) {
destroy_flag = 1;
}
struct session_data {
int fd;
};
struct pthread_routine_tool {
struct lws_context *context;
struct lws *wsi;
};
static int websocket_write_back(struct lws *wsi_in, char *str, int str_size_in)
{
if (str == NULL || wsi_in == NULL)
return -1;
int n;
int len;
char *out = NULL;
if (str_size_in < 1)
len = strlen(str);
else
len = str_size_in;
out = (char *)malloc(sizeof(char)*(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING));
//* setup the buffer*/
memcpy (out + LWS_SEND_BUFFER_PRE_PADDING, str, len );
//* write out*/
n = lws_write(wsi_in, out + LWS_SEND_BUFFER_PRE_PADDING, len, LWS_WRITE_TEXT);
printf(KBLU"[websocket_write_back] %s\n"RESET, str);
//* free the buffer*/
free(out);
return n;
}
static int ws_service_callback(
struct lws *wsi,
enum lws_callback_reasons reason, void *user,
void *in, size_t len)
{
switch (reason) {
case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf(KYEL"[Main Service] Connect with server success.\n"RESET);
connection_flag = 1;
break;
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
printf(KRED"[Main Service] Connect with server error.\n"RESET);
destroy_flag = 1;
connection_flag = 0;
break;
case LWS_CALLBACK_CLOSED:
printf(KYEL"[Main Service] LWS_CALLBACK_CLOSED\n"RESET);
destroy_flag = 1;
connection_flag = 0;
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
printf(KCYN_L"[Main Service] Client recvived:%s\n"RESET, (char *)in);
if (writeable_flag)
destroy_flag = 1;
break;
case LWS_CALLBACK_CLIENT_WRITEABLE :
printf(KYEL"[Main Service] On writeable is called. send byebye message\n"RESET);
websocket_write_back(wsi, "{\"command\":\"subscribe\",\"identifier\":\"{\\\"channel\\\":\\\"DevicesChannel\\\",\\\"share_token\\\":\\\"D0E91\\\"}\"}", -1);
websocket_write_back(wsi, "{\"command\":\"message\",\"identifier\":\"{\\\"channel\\\":\\\"DevicesChannel\\\",\\\"share_token\\\":\\\"D0E91\\\"}\",\"data\":\"{\\\"value\\\":100,\\\"action\\\":\\\"set_buzz\\\"}\"}", -1);
writeable_flag = 1;
break;
default:
break;
}
return 0;
}
static void *pthread_routine(void *tool_in)
{
struct pthread_routine_tool *tool = tool_in;
printf(KBRN"[pthread_routine] Good day. This is pthread_routine.\n"RESET);
//* waiting for connection with server done.*/
while(!connection_flag)
usleep(1000*20);
//*Send greeting to server*/
lws_callback_on_writable(tool->wsi);
}
int main(void)
{
//* register the signal SIGINT handler */
struct sigaction act;
act.sa_handler = INT_HANDLER;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction( SIGINT, &act, 0);
struct lws_context *context = NULL;
struct lws_context_creation_info info;
struct lws *wsi = NULL;
struct lws_protocols protocol;
memset(&info, 0, sizeof info);
info.port = CONTEXT_PORT_NO_LISTEN;
info.iface = NULL;
info.protocols = &protocol;
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;
info.extensions = lws_get_internal_extensions();
info.gid = -1;
info.uid = -1;
info.options = 0;
protocol.name = "websockets";
protocol.callback = &ws_service_callback;
protocol.per_session_data_size = sizeof(struct session_data);
protocol.rx_buffer_size = 0;
protocol.id = 0;
protocol.user = NULL;
context = lws_create_context(&info);
printf(KRED"[Main] context created.\n"RESET);
if (context == NULL) {
printf(KRED"[Main] context is NULL.\n"RESET);
return -1;
}
wsi = lws_client_connect(context, "mobu1.herokuapp.com", 443, 1,
"/cable", "mobu1.herokuapp.com", "link.motorbunny.com",
if (wsi == NULL) {
printf(KRED"[Main] wsi create error.\n"RESET);
return -1;
}
printf(KGRN"[Main] wsi create success.\n"RESET);
struct pthread_routine_tool tool;
tool.wsi = wsi;
tool.context = context;
pthread_t pid;
pthread_create(&pid, NULL, pthread_routine, &tool);
pthread_detach(pid);
while(!destroy_flag)
{
lws_service(context, 50);
}
lws_context_destroy(context);
return 0;
}
The result of running the above program is this:
As you can see, the periodic pings from server to my client are being picked up, but the lws_callback_on_writable(wsi); seems to have no effect as the LWS_CALLBACK_CLIENT_WRITEABLE callback never gets called. Additionally, if I call websocket_write_back() directly anywhere else, it doesn't seem to be sending anything to the server, and no acknowledgement is present either.
Is there something obvious I am doing wrong?
EDIT 1:
I found this neat wscat, where I can replicate the results from Chrome:
Now the question is, how can I interface this with my C program in a way that it can wait for the Welcome message from the server, and then send two messages?
And better yet, how to stay connected, so that my program can send multiple commands at different points of time without having to do the handshake all the time?
The reason why the LWS_CALLBACK_CLIENT_WRITEABLE callback never got called was because this particular server uses non-standard handshake. So, to bypass this, I forked a fork of libwsclient and modified the handshake checking function to not fail on mismatch. I also added an optional Origin header.
Now, all I need to do in my original program is
wsclient *client;
char sync_str[6];
void mb_send(int power, char* type)
{
char cmd[2048];
sprintf (cmd, "{\"command\":\"message\",\"identifier\":\"{\\\"channel\\\":\\\"DevicesChannel\\\",\\\"share_token\\\":\\\"%s\\\"}\",\"data\":\"{\\\"value\\\":%d,\\\"action\\\":\\\"set_%s\\\"}\"}",sync_str,power,type);
libwsclient_send(client,cmd);
}
void mb_connect()
{
char cmd[2048];
sprintf (cmd, "{\"command\":\"subscribe\",\"identifier\":\"{\\\"channel\\\":\\\"DevicesChannel\\\",\\\"share_token\\\":\\\"%s\\\"}\"}",sync_str);
libwsclient_send(client,cmd);
mb_send(0,"buzz");
}
int nop()
{
return 0;
}
int main()
{
client = libwsclient_new_extra("wss://mobu1.herokuapp.com/cable","https://link.motorbunny.com");
if(!client) {
fprintf(stderr, "Unable to initialize new WS client.\n");
exit(1);
}
libwsclient_onopen(client, &nop);
libwsclient_onmessage(client, &nop);
libwsclient_onerror(client, &nop);
libwsclient_onclose(client, &nop);
libwsclient_run(client);
...
mb_connect();
...
mb_send(200,"buzz");
mb_send(40,"twirl");
...
mb_send(0,"buzz");
mb_send(0,"twirl");
}
I found an ugly hack to make my C program send WebSocket messages to a server via the wsta program.
It requires a text file, into which my program will append whenever it wants to send a message to the server. The new lines are then picked up in the background by tail -f, and are piped to wsta which maintains the connection. Output can be redirected to /dev/null so that the wsta output doesn't pollute the output of my program, or sent to a file if responses from the server need to be parsed.
The whole script to make this work would look like this (or you could use FIFO pipe with cat instead of a file with tail):
#!/bin/bash
touch commands.txt
tail commands.txt -f -n 0 | wsta --header "Origin: https://link.motorbunny.com" "wss://mobu1.herokuapp.com/cable" &> /dev/null &
./program
In the C program, I just need to write to the commands.txt file:
FILE* cmd;
char sync_str[6];
void mb_connect()
{
fprintf (cmd, "{\"command\":\"subscribe\",\"identifier\":\"{\\\"channel\\\":\\\"DevicesChannel\\\",\\\"share_token\\\":\\\"%s\\\"}\"}\n",sync_str);
fflush(cmd);
}
void mb_send(int power, char* type)
{
fprintf (cmd, "{\"command\":\"message\",\"identifier\":\"{\\\"channel\\\":\\\"DevicesChannel\\\",\\\"share_token\\\":\\\"%s\\\"}\",\"data\":\"{\\\"value\\\":%d,\\\"action\\\":\\\"set_%s\\\"}\"}\n",sync_str,power,type);
fflush(cmd);
}
int main()
{
cmd = fopen ("commands.txt","w");
...
mb_connect();
...
mb_send(200,"buzz");
...
mb_send(0,"buzz");
}
How can I get the interface name for the IP address in linux from C code ?
e.g. I'd like to get the interface name ( like etho , eth1 , l0 ) assigned for the IP address 192.168.0.1
Using /proc/net/arp you can match it. Here is a command line tool example.
usage: getdevicebyip 192.168.0.1
#include <stdio.h>
#include <fcntl.h>
int main(int argc, char **argv){
if (argc < 2) return 1;
FILE *fp = fopen("/proc/net/arp", "r");
char ip[99], hw[99], flags[99], mac[99], mask[99], dev[99], dummy[99];
fgets(dummy, 99, fp); //header line
while (fscanf(fp, "%s %s %s %s %s %s\n", ip, hw, flags, mac, mask, dev) != EOF)
if (!strcmp(argv[1],ip))
printf("%s\n",dev);
return 0;
}
You can use getifaddrs. See man 3 getifaddrs for usage information. This will only work on a Unix-like systems.
netlink is a way to do this on Linux. I think it might even be a proper way to do it on Linux (even though it isn't portable).
The strategy is:
Get a list of addresses on interfaces from the kernel by sending a netlink message.
Find the address you want (I have hard coded the one I want as address_dq) and record its interface (a number at this stage)
Get a list of interfaces by sending another netlink message,
Find the number of the interface matching the number you recorded in step (2).
Get the name of the interface.
The code below is not pretty, but I'm sure you could do a better job of it. I have been a especially sloppy by not checking for a multipart message (checking for the NLM_F_MULTI flag and for a message type of NLMSG_DONE is the way to do it). Instead I have just assumed the response to the first message is multipart -- it is on my machine -- and chewed up the NLMSG_DONE message which follows.
Code...
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, void ** argv) {
// This is the address we want the interface name for,
// expressed in dotted-quad format
char * address_dq = "127.0.0.1";
// Convert it to decimal format
unsigned int address;
inet_pton(AF_INET, address_dq, &address);
char buf[16384];
// Our first message will be a header followed by an address payload
struct {
struct nlmsghdr nlhdr;
struct ifaddrmsg addrmsg;
} msg;
// Our second message will be a header followed by a link payload
struct {
struct nlmsghdr nlhdr;
struct ifinfomsg infomsg;
} msg2;
struct nlmsghdr *retmsg;
// Set up the netlink socket
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
// Fill in the message
// NLM_F_REQUEST means we are asking the kernel for data
// NLM_F_ROOT means provide all the addresses
// RTM_GETADDR means we want address information
// AF_INET means limit the response to ipv4 addresses
memset(&msg, 0, sizeof(msg));
msg.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
msg.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
msg.nlhdr.nlmsg_type = RTM_GETADDR;
msg.addrmsg.ifa_family = AF_INET;
// As above, but RTM_GETLINK means we want link information
memset(&msg2, 0, sizeof(msg2));
msg2.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
msg2.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
msg2.nlhdr.nlmsg_type = RTM_GETLINK;
msg2.infomsg.ifi_family = AF_UNSPEC;
// Send the first netlink message
send(sock, &msg, msg.nlhdr.nlmsg_len, 0);
int len;
// Get the netlink reply
len = recv(sock, buf, sizeof(buf), 0);
retmsg = (struct nlmsghdr *)buf;
// Loop through the reply messages (one for each address)
// Each message has a ifaddrmsg structure in it, which
// contains the prefix length as a member. The ifaddrmsg
// structure is followed by one or more rtattr structures,
// some of which (should) contain raw addresses.
while NLMSG_OK(retmsg, len) {
struct ifaddrmsg *retaddr;
retaddr = (struct ifaddrmsg *)NLMSG_DATA(retmsg);
int iface_idx = retaddr->ifa_index;
struct rtattr *retrta;
retrta = (struct rtattr *)IFA_RTA(retaddr);
int attlen;
attlen = IFA_PAYLOAD(retmsg);
char pradd[128];
// Loop through the routing information to look for the
// raw address.
while RTA_OK(retrta, attlen) {
if (retrta->rta_type == IFA_ADDRESS) {
// Found one -- is it the one we want?
unsigned int * tmp = RTA_DATA(retrta);
if (address == *tmp) {
// Yes!
inet_ntop(AF_INET, RTA_DATA(retrta), pradd, sizeof(pradd));
printf("Address %s ", pradd);
// Now we need to get the interface information
// First eat up the "DONE" message waiting for us
len = recv(sock, buf, sizeof(buf), 0);
// Send the second netlink message and get the reply
send(sock, &msg2, msg2.nlhdr.nlmsg_len, 0);
len = recv(sock, buf, sizeof(buf), 0);
retmsg = (struct nlmsghdr *)buf;
while NLMSG_OK(retmsg, len) {
struct ifinfomsg *retinfo;
retinfo = NLMSG_DATA(retmsg);
if (retinfo->ifi_index == iface_idx) {
retrta = IFLA_RTA(retinfo);
attlen = IFLA_PAYLOAD(retmsg);
char prname[128];
// Loop through the routing information
// to look for the interface name.
while RTA_OK(retrta, attlen) {
if (retrta->rta_type == IFLA_IFNAME) {
strcpy(prname, RTA_DATA(retrta));
printf("on %s\n", prname);
exit(EXIT_SUCCESS);
}
retrta = RTA_NEXT(retrta, attlen);
}
}
retmsg = NLMSG_NEXT(retmsg, len);
}
}
}
retrta = RTA_NEXT(retrta, attlen);
}
retmsg = NLMSG_NEXT(retmsg, len);
}
}
When run as above, returns Address 127.0.0.1 on lo.
Using "192.168.1.x" instead of "127.0.0.1" it instead returns Address 192.168.1.x on eth0.
I have recently been getting involved with having to utilize pf_ring / libpcap. I have never developed with libpcap or pf_ring so please forgive what might appear to be a silly question, as network programming is semi new to me... In broad terms what I am trying to do is access the if_index for packets received. I currently have a simple raw packet sniffer created with "C" utilizing pf_ring as shown below:
#include <pcap.h>
#include <pfring.h>
#include <string.h>
#include <stdlib.h>
#define MAXBYTES2CAPTURE 2048
void processRingPacket(const struct pfring_pkthdr* pkthdr, const u_char* packet, const u_char *arg)
{
int i=0, *counter = (int*)arg;
printf("Packet Count: %d ", ++(*counter));
printf("Received Packet Size: %d ", pkthdr->len);
printf("ifIndex: %d ", pkthdr->extended_hdr.if_index);
printf("Payload:\n");
for(i=0; i < pkthdr->len; i++)
{
if(isprint(packet[i]))
{
printf("%c ", packet[i]);
}
else
{
printf(". ");
}
if((i % 16 == 0) && (i != 0) || (i == pkthdr->len-1))
{
printf("\n");
}
}
return;
}
int main()
{
int count = 0;
char *device = "eth0";
printf("Opening Device: %s\n", device);
pfring* ring = pfring_open(device, MAXBYTES2CAPTURE, 0);
pfring_enable_ring(ring);
pfring_loop(ring, processRingPacket, (u_char*)&count, 1);
return 0;
}
Looking at the pfring_pkthdr struct within the pf_ring API, I should be able to do the following:
pkthdr->extended_hdr.if_index
However, when I try to print out the index it just prints 0. I am guessing the if_index is not actually being set, as when I actually call the pf_ring function to get the device if index, I actually receive a value for the specified device:
pfring_get_device_ifindex (pfring *ring, char *device_name, int *if_index)
The problem is I am trying to view the if_index for each packet, hence within the call back function "processRingPacket" there is no way to generically specify the device. I say generically here because there will be two interfaces capturing packets. Any ideas on what my rookie mistake might be?
I think you need to pass in PF_RING_LONG_HEADER as a flag to pfring_open(). So it becomes, pfring_open(device, MAXBYTES2CAPTURE, PF_RING_LONG_HEADER);
If pkthdr->extended_hdr.if_index isn't set in the callback function, you can always pass it in to your callback function in the arg argument.
struct Dev {
int count;
int if_index;
};
...
char *device = "eth0";
struct Dev dev;
dev.count = 0;
dev.if_index = if_nametoindex(device); //from #include <net/in.h>
printf("Opening Device: %s\n", device);
pfring* ring = pfring_open(device, MAXBYTES2CAPTURE, 0);
pfring_enable_ring(ring);
pfring_loop(ring, processRingPacket, (u_char*)&dev, 1);
And recover that in the callback function:
void processRingPacket(const struct pfring_pkthdr* pkthdr, const u_char* packet, const u_char *arg)
{
struct Dev *dev = (struct Dev*)arg;
int i=0, *counter = (int*)&dev->count;
//and use dev->if_index; whenever you need to.
I have client and server code communicating with each other using protobuf-c over 0mq
below is the client cod snipped
void *context = zmq_ctx_new ();
void *requester = zmq_socket (context, ZMQ_REQ);
char collector[100];
char buffer[MAX_MSG];
sprintf(collector,"tcp://%s:%s",argv[2],argv[3]);
zmq_connect (requester, collector);
LogMsg proto_msg = LOG_MSG__INIT;
void *buf; // Buffer to store serialized data
unsigned len; // Length of serialized data
proto_msg.name=argv[1];//assigning arg1 the node name
proto_msg.ip="127.0.0.1"; //TODO get IP im connected to
proto_msg.pid=getpid();
proto_msg.has_pid = 1;
//sending Hello to Collector to register
proto_msg.level = "HELLO";
len = log_msg__get_packed_size (&proto_msg);
buf = malloc (len);
log_msg__pack (&proto_msg, buf);
printf("Writing %d serialized bytes to socket: Handshaking with Collector\n",len); // See the length of message
zmq_send(requester, buf,len, 0);
on the Server side i have the following code
#include "generator.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");
uint8_t buffer[MAX_MSG];
int i=0;
assert (rc == 0);
zmq_recv (responder, buffer, MAX_MSG, 0);
printf ("recieved -> %s\n",buffer);
LogMsg *ptr_msg;
ptr_msg = log_msg__unpack(NULL,i,buffer); // Deserialize the serialized input
if (ptr_msg == NULL)
{ // Something failed
fprintf(stderr,"error unpacking incoming message\n");
return 1;
}
log_msg__free_unpacked(ptr_msg,NULL);
return 0;
}
But when the server receives the message it is giving the following error
recieved ->
B1 127.0.0.1??"HELLO/??
message 'Log_msg': missing required field 'name'
For reference .proto file is as below
message Log_msg
{
required string name=1; //Node Name
optional string IP=2 [default = "127.0.0.1"]; //Node IP Addr
optional int32 PID=3 [default = 9999]; //Process ID
optional string level=4 [default = "INFO"]; //Log Info Level
optional int64 datim=5; //UNIX Time Stamp
optional string msg=6; //Log message
}
I assume when i am transmitting it on wire then it gets corrupted. Any ideas how i can send it properly. Examples online show this for c++. I need for C.
zmq_send and zmq_recv seems to handle zmq_msg_t structures rather than just the buffer.
Maybe you should try to create such structures rather than just sending your buffer ?
See the examples in http://api.zeromq.org/2-1:zmq-send and http://api.zeromq.org/2-1:zmq-recv