Sending a structure over socket in c - c

I am writing a program which uses socket programming in c.
In this program a client and server keep transmitting and receiving data.
When I send and receive integers over the socket using this kind of code
//in the program sending data
int data;
len= send(s,(char *)&(data),sizeof(data),0);
//in the program receiving data
int num;
len = recv(s,&num, sizeof(num) , 0);
The above code is working fine and I am able to transmit and receive numbers.
In one case I am trying to send a structure of the form
struct sample{
int num;
char chain[10*hops+10];
};
//in the program sending data
struct sample s1;
len= send(s,(char *)&(s1),sizeof(s1),0);
//in the program receiving data
struct sample s2;
len = recv(s,&s2, sizeof(s2) , 0);
In the example where I am trying to send and receive structure it is not working. How to send and receive the struct successfully ?
Note:
1) Hops is a pre defined variable.The value of hops is same in both the programs.
2) By not working I meant : when I receive the struct and print the value in the the num. It is printing not the same value but zero!

if you are trying to send the struct you must use serialization and deserialization, read about that, you can start with :
Serialization issues while sending struct over socket

Related

Passing multiple buffers with iovec in C Linux sockets

I'm writing a linux C client-server programs that communicates with each other with unix domain sockets and passes couple of buffers each time.
I'm using ioverctors but for some reasons the server program only receives the first io vector.
Any idea ?
I attached the relevant code snippets.
Client code:
struct iovec iov[2];
struct msghdr mh;
int rc;
char str1[] = "abc";
char str2[] = "1234";
iov[0].iov_base = (caddr_t)str1;
iov[0].iov_len = sizeof(str1);
iov[1].iov_base = (caddr_t)str2;
iov[1].iov_len = sizeof(str2);
memset(&mh, 0, sizeof(mh));
mh.msg_iov = iov;
mh.msg_iovlen = 2;
n = sendmsg(sockfd, &mh, 0); /* no flags used*/
if (n > 0) {
printf("Sendmsg successfully executed\n");
}
}
Server code:
{
struct sockaddr_un *client_sockaddr = (sockaddr_un *)opq;
struct msghdr msg;
struct iovec io[2];
char buf[16];
char buf2[16];
io[0].iov_base = buf;
io[0].iov_len = sizeof(buf);
io[1].iov_base = buf2;
io[1].iov_len = sizeof(buf2);
msg.msg_iov = io;
msg.msg_iovlen = 2;
int len = recvmsg(sock, &msg, 0);
if (len > 0) {
printf("recv: %s %d %s %d\n", msg.msg_iov[0].iov_base, msg.msg_iov[0].iov_len, msg.msg_iov[1].iov_base, msg.msg_iov[1].iov_len);
}
return 0;
}
The output i'm getting from the server:
recv: abc 16 16
sendmsg(), writev(), pwritev(), and pwritev2() do not operate on multiple buffers, but one discontiguous buffer. They operate exactly as if you'd allocate a large enough temporary buffer, gather the data there, and then do the corresponding syscall on the single temporary buffer.
Their counterparts recvmsg(), readv(), preadv(), and preadv2() similarly do not operate on multiple buffers, only on one discontiguous buffer. They operate exactly as if you'd allocate a large enough temporary buffer, receive data into that buffer, then scatter the data from that buffer to the discontiguous buffer parts.
Unix domain datagram (SOCK_DGRAM) and seqpacket (SOCK_SEQPACKET) sockets preserve message boundaries, but stream sockets (SOCK_STREAM) do not. That is, using a datagram or seqpacket socket you receive each message as it was sent. With a stream socket, message boundaries are lost: two consecutively sent messages can be received as a single message, and you can (at least in theory) receive a partial message now and the rest later.
You can use the Linux-specific sendmmsg() function to send several messages in one call (using the same socket). If you use an Unix domain datagram or seqpacket socket, these will then retain their message boundaries.
Each message is described using a struct mmsghdr. It contains struct msghdr msg_hdr; and unsigned int msg_len;. msg_hdr is the same as you use when sending a single message using e.g. sendmsg(); you can use more than one iovec for each message, but the recipient will receive them concatenated into a single buffer (but can scatter that buffer using e.g. recvmsg()). msg_len will be filled in by the sendmmsg() call: the number of bytes sent for that particular message, similar to the return value of e.g. sendmsg() call when no errors occur.
The return value from the sendmmsg() call is the number of messages sent successfully (which may be fewer than requested!), or -1 if an error occurs (with errno indicating the error as usual). Thus, you'll want to write a helper function or a loop around sendmmsg() to make sure you send all the messages. For portability, I recommend a helper function, because you can then provide another based on a loop around sendmsg() for use when sendmmsg() is not available.
The only real benefit of sendmmsg() is that you need fewer syscalls to send a large number of messages: it boosts efficiency in certain situations, that's all.

Cant get the right outcome with strtok() , need help , c

Am working on a project where it is a communication between server client. Server opens a specific file and stores the message from the client in a buffer using while(1) for repeated communication. All am trying is manage the message like, when client sends this message : AT+REG1=5 , i want to split it ("=") in order to determine operations and values : operation = AT+REG1 And value is 5. In my code i have a struct with informations for "operation" and "value". I use strtok function to split message but it doesnt work right and i dont know why , for example i send through client AT+REG1=5 and when i split the message like :
token=strtok("AT+REG1=5","="); // points to AT+REG1
value=strtok(NULL,"="); // points to the value but returns null
It returns that value is (null) despite that it must return "5".
My build for that is :
typedef enum operation{
insert,
read_reg,
info
}Operation;
typedef struct request{
Operation operation;
int ID;
int **regs;
}Request;
Function that handles the split of message:
Request *parse_request(char *buffer){
char *token=NULL,*value=NULL;
Request *rep=NULL;
rep=(Request*)malloc(sizeof(Request));
token=strtok(buffer,"=");
printf("token:%s\n",token);
value=strtok(NULL," ");
printf("value=%s\n",value);
return rep;
}
And now the main loop where i call this function after receiving the message :
char buffer[SIZE];
while(1){
//Clean buffer
memset(buffer,0,SIZE);
FD_ZERO(&readfd);
FD_SET(fd,&readfd);
timeout.tv_sec=100;
timeout.tv_usec=0;
status=select(40,&readfd,NULL,NULL,&timeout);
if(status==0){
printf("Cannot receive data from client\n");
printf("\tTime Out\n");
exit(1);
}
read_num=read(fd,buffer,sizeof(buffer));
if(read_num<0) perror("Error in reading file descriptor\n");
if(read_num>0){
request=parse_request(buffer);
break;
}
}
The main problem here is that strtok returns null in at value parameter despite that the message is AT+REG1=5 and it must show "5".

Extract data (string, char, etc.) from an incoming stream on a C socket

How do I extract the actual data (in a form of human readable string, character, an integer etc.) from an incoming stream on a socket in C? The point of this is to be able to act on the contents of the incoming message.
struct netconn *client = NULL;
struct netconn *nc = netconn_new(NETCONN_TCP);
netconn_bind(nc, IP_ADDR_ANY, 8569);
netconn_listen(nc);
while (1) {
err_t err = netconn_accept(nc, &client);
if (err == ERR_OK) {
struct netbuf *nb;
if ((err = netconn_recv(client, &nb)) == ERR_OK) {
/* INTERPRETE INCOMING DATA HERE?? */
}
netbuf_delete(nb);
}
netconn_close(client);
netconn_delete(client);
}
The client connects and sends, say 'testing123' string. How do I go about interpreting this string on the 'server' side?
The point of this exercise is to be able to trigger desired behaviour on the receiving end with the use of appropriate 'command' sent across the local network to WLAN-attached ESP8266 microcontroller.
Ps. I realize it's probably very primitive mechanism so I would appreciate some feedback regarding this matter. Any thoughts/ideas/suggestions greatly appreciated.
As your server can't know what and how the data is being send you need to specify a common message or some kind of seperator between words if you choose to use strings.
For example you could use a | as a seperator so that you would input the following on your client: testing|123
On your server you would now need to search for the | seperator and divide the incoming data so you have a string "testing" and a int "123".
As another aproach you could define yourself a interface based on numbers with the help of a struct.
For example:
typedef struct
{
int cmd;
int subCmd;
} cmdStruct;
In this you would need to deserialize the incoming bytes and parse them to the command structure and act upon the received command. This would include that you send the command accordingly.
Trivial excercise as it turns out. The netbuf structure have 'placeholders' for the contents of incoming data and it's lenght;
netbuf_data(nb, &data, &len);
In my case;
/* INTERPRETE INCOMING DATA HERE?? */
void *data;
u16_t len;
netbuf_data(nb, &data, &len);
char * theData = data;
printf("%s\n", theData);
prints the incoming string on-screen.

Send a XDR struct over a socket with C in Linux

I'm writing a server that send an XDR struct over a socket.
Using Wireshark I see that my client correctly send an XDR message to the server BUT I don't see any data go from the server to the client. But the code seems to be correct as it is the same used for the client. I have see that the problem is xdr_Response. Is there any mistake on it? Thanks to all
XDR xdrs_w;
Response y;
stream_socket_w = fdopen(s, "w");
xdrstdio_create(&xdrs_w, stream_socket_w, XDR_ENCODE);
y.error = 0;
y.result = 5.7;
xdr_Response(&xdrs_w, &y);
fflush(stream_socket_w);
with:
struct Response {
bool_t error;
float result;
};
typedef struct Response Response;
I'm not very expert of XDR, but I found a way that worked to receive data from XDR with a socket connection (on TCP). First you have to do recv to receive the data from your client, then call xdrmem_create(), that need the XDR structure that you'll use to the reading, a buffer (a string), the return value of recv(), and you have to use XDR_DECODE because you're writing from XDR that's codified.
You have to write something like this:
l = recv(socket, buffer, BUFFERDIM, 0);
xdrmem_create(&xdrs_w, buff, l, XDR_DECODE );
if(!xdr_Response(&xdrs_w, &y) {
fprintf(stdout, "Error XDR\n");
}
fprintf(stdout, "Received: %f", y.result);
and y should be filled in. Note that buffer is different from buff. I prefer to do this instead of use fd_open, you've only to create the xdr and call xdr_Response.

Sent UDP package to NTP server and receive time (lwip, Cortex M3, Stellaris LM3S6965 Evaluation Board)

I'm working with Cortex M3, Stellaris® LM3S6965 Evaluation Board. I want to display the time of a NTP server on my oled screen. First I want to get a reply from the NTP server. I searched that the server works with UDP. And It gives me a timestamp. I'm using the LWIP library.
I'm trying to sent the server an UDP packet and I want to display the recieved packet data on the display (the timestamp)..
So I think I have to sent a udp package to the TNP server and recieve the timestamp.
But somehow its not working. I hope you guys can help me find a solution.
EDIT:
I also found some more information about NTP here
Updated program:
// Function gets called when we recieve data
err_t RecvUTPCallBack(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port){
RIT128x96x4Enable(1000000);
RIT128x96x4StringDraw("ENTERING CALLBACK", 40, 40, 11);
volatile int totaal_lengte=0;
totaal_lengte = p->tot_len;
volatile int line=40;
while(1){
RIT128x96x4Enable(1000000);
RIT128x96x4StringDraw(p->payload+1, 0, line, 15);
line+=8;
if(p->len != p->tot_len){
p=p->next;
}
else break;
}
pbuf_free(p);
}
int main(void){
//UDP
struct udp_pcb * udp_con_new;
struct ip_addr ntp_server;
udp_con_new = udp_new();
IP4_ADDR(&ntp_server,65,55,21,13); // time.windows.com
udp_connect(udp_con_new,&ntp_server,123);
struct pbuf * p;
p = 0;
udp_send(udp_con_new, p);
//udp_recv(upcb,RecvUTPCallBack, recv_arg);
}
You're not sending any data. UDP is connection-less, and these random docs for the udp_connect() function (which do seem to match what you're using) say:
This function does not generate any network traffic, but only sets the remote address of the pcb.
You must construct a valid request packet for NTP, and then send it using udp_send(). For details on how to do this, and generally a lot of information on NTP which you seem to need, read the current IEEE specification. Enjoy.

Resources