Plz Help ..Strucs-->U_char arrays<--Structs

  • Thread starter ANaiveProgrammer
  • Start date
A

ANaiveProgrammer

Hi all
I have been trying to send a struct over socket. I tried to assign the
values of struct
to unsigned char array. I have attached both .c files at the bottom.
'Client.c' takes a
struct, arrange the struct in u_char array and send the u_char array
to 'Server.c'. Now
'Server.c' takes the u_char array and assign to the struct and
displays its values.
Now im totally stumped and im facing following problems though i have
tried to locate errors
thoroughly , but im unable to understand what is the problem

a-)I am not sure about usage of 'memcpy'. My struct contains two
u_int's and one char array of 5
elements.Now im doing the following to assign my struct elements to
u_char array in 'parse_struct'
function in 'Client.c' file

memcpy(off,(void *)&(s->a),sizeof(s->a));
off += sizeof(s->a);
memcpy(off,(void *)&(s->b),sizeof(s->b));
off += sizeof(s->b);
/*
Now im really stumped about the following, is it correct? I think
it should work because 'memcpy' needs addresses of elements to be
copied and
the number of bytes and i think '&s->name' will assign the string
'hello'
to off, but plz correct me if im wrong....
*/
memcpy(off,(void *)&s->name,sizeof(s->name));

b-)Now in 'Server.c' file im using memcpy as follows
memcpy( &(dest->a), off, sizeof(dest->a));
off += sizeof(dest->a);
memcpy(&(dest->b),off,sizeof(dest->b));
off += sizeof(dest->b);
//Again , to me, following line is Ok
memcpy((char *)&(dest->name),off,sizeof(dest->name));
because as memcpy returns a pointer to destination and my
following check successfuly returns the correct value of
'Hello' after the execution of following 'while' loop

char *ptr;
memcpy(&(dest->b),off,sizeof(dest->b));
off += sizeof(dest->b);
ptr = (unsigned char *)memcpy((char
*)&(dest->name),off,sizeof(dest->name));
printf("butt_to_struct()--ptr(dest-->name)...\n");
while( *ptr != 'o' )
printf("%c",*ptr++);
printf("%c\n",*ptr);

c-)Now to execute my task , i run 'Server.c' first and then 'Client.c'
from other
terminal. Now for the first time program runs fine. Then i terminate
both 'Server.c'
and 'Client.c' programs and when i run these two files again without
ever changing them
then 'Client.c' does execute but after the execution it prints 'Pipe
Broken' and exits. Now
Though 'Client.c' has executed but when i switch my terminal to see
whts going in 'Server.c' program
it is still waiting for a connection.
I mean this is absurd, why the heck program i.e 'Client.c' tells me
'Broken Pipe'
when being executed for the second time? This is beyond my
comprehension :(

d-) Last but not the least , in the main() of 'Server.c' when i
successfully
return from buff_to_struct() function and try to do the following
printf("Value of name = %s\n",s.name);
it prints
HelloBx
though it should have printed only 'Hello', now where these last two
bytes i.e. 'Bx'
came from ?
I know this must be time consuming for you, but im really stumped
about this so
i will really appreciate any kind of help. Thanks a lot for your
concern & time.....
Thanks in anticipation.

Regards....

Both 'Server.c' And 'Client.c' are attached below & im using gcc over
Red hat linux 8.0

Server.c
-----------
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>

typedef struct{
uint8_t a;
uint8_t b;
char name[5];
}str;

void buff_to_struct(str *dest, unsigned char *src){


unsigned char *off;
int len;
len =0;
off = src;


memcpy( &(dest->a), off, sizeof(dest->a));

off += sizeof(dest->a);
char *ptr;

memcpy(&(dest->b),off,sizeof(dest->b));
off += sizeof(dest->b);
ptr = (unsigned char *)memcpy((char
*)&(dest->name),off,sizeof(dest->name));
printf("butt_to_struct()--ptr(dest-->name)...\n");
while( *ptr != 'o' )
printf("%c",*ptr++);
printf("%c\n",*ptr);




}
int main()

{
str s;
int fd;
printf("Size of str--ptr..%d\n",sizeof(str));
struct sockaddr_in server,client;

fd = socket(AF_INET,SOCK_STREAM,0);
server.sin_family = AF_INET;
server.sin_port =htons(1800);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(fd, (struct sockaddr *)&server,sizeof(server));
listen(fd,2);
printf("Listening to Connetions...\n");

int len;
len = sizeof(client);
int connfd;
connfd = accept(fd, (struct sockaddr*)&client, &len);

unsigned char src[7];
int readlen ;
read(connfd,src,7);


buff_to_struct(&s,src);


printf("Value received(s.a)---=%d\n",s.a);
printf("Value of s.b =%d\n",s.b);
//Problem lies in the following, it *must* print 'Hello' but following
//line prints 'HelloBx' , why??????
printf("Value of name = %s\n",s.name);
printf("\n");

close(fd);
return 0;
}









________________________________________________________________________________________
Client.c
---------
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

typedef struct{
uint8_t a;
uint8_t b;
char name[5];

}str;

int parse_struct(unsigned char *dest,str *s){

unsigned char *off;
off = dest;

memcpy(off,(void *)&(s->a),sizeof(s->a));

off += sizeof(s->a);
memcpy(off,(void *)&(s->b),sizeof(s->b));

off += sizeof(s->b);
char *ptr;

ptr = (char *)memcpy(off,(void *)&s->name,sizeof(s->name));
//Purpose of following 'while' is to check the contents of 'off'
while (*ptr !='o')
printf("%c",*ptr++);
printf("%c\n",*ptr);
//Aforementioned while correctly prints the value of 'ptr'
printf("(Parse_struct) off=%s\n",off);

off += sizeof(s->name);
char ch='\0';
memcpy(off,(void *)& ch, sizeof(ch));

int len ;
len = sizeof(s->a)+sizeof(s->b)+sizeof(s->name);
return len;

}
int main(){

str s;
s.a = 10;
s.b = 20;
strcpy(s.name,"Hello");


int fd;
struct sockaddr_in client;
fd = socket(AF_INET,SOCK_STREAM,0);
client.sin_family = AF_INET;
client.sin_port = htons(1800);
client.sin_addr.s_addr = inet_addr("127.0.0.1");



connect(fd,(struct sockaddr*)&client,sizeof(client));


printf("Connected and Writing data...\n");

unsigned char buff[7];
int len;
len = parse_struct(buff,&s);

write(fd,buff,len);


exit(0);

}
 
?

=?ISO-8859-1?Q?Bj=F8rn_Augestad?=

ANaiveProgrammer wrote:
[Lots of stuff snipped]
typedef struct{
uint8_t a;
uint8_t b;
char name[5];

}str;
[snip]

strcpy(s.name,"Hello");

Here's at least one error. You strcpy() 6 bytes into a 5 byte array. The
rest looked more or less ok, but you can drop lots of casts to void*.

HTH
Bjørn

[snip]
 
L

Larry I Smith

ANaiveProgrammer said:
Hi all
I have been trying to send a struct over socket. I tried to assign the
values of struct
to unsigned char array. I have attached both .c files at the bottom.
'Client.c' takes a
struct, arrange the struct in u_char array and send the u_char array
to 'Server.c'. Now
'Server.c' takes the u_char array and assign to the struct and
displays its values.
Now im totally stumped and im facing following problems though i have
tried to locate errors
thoroughly , but im unable to understand what is the problem

a-)I am not sure about usage of 'memcpy'. My struct contains two
u_int's and one char array of 5
elements.Now im doing the following to assign my struct elements to
u_char array in 'parse_struct'
function in 'Client.c' file

memcpy(off,(void *)&(s->a),sizeof(s->a));
off += sizeof(s->a);
memcpy(off,(void *)&(s->b),sizeof(s->b));
off += sizeof(s->b);
/*
Now im really stumped about the following, is it correct? I think
it should work because 'memcpy' needs addresses of elements to be
copied and
the number of bytes and i think '&s->name' will assign the string
'hello'
to off, but plz correct me if im wrong....
*/
memcpy(off,(void *)&s->name,sizeof(s->name));

b-)Now in 'Server.c' file im using memcpy as follows
memcpy( &(dest->a), off, sizeof(dest->a));
off += sizeof(dest->a);
memcpy(&(dest->b),off,sizeof(dest->b));
off += sizeof(dest->b);
//Again , to me, following line is Ok
memcpy((char *)&(dest->name),off,sizeof(dest->name));
because as memcpy returns a pointer to destination and my
following check successfuly returns the correct value of
'Hello' after the execution of following 'while' loop

char *ptr;
memcpy(&(dest->b),off,sizeof(dest->b));
off += sizeof(dest->b);
ptr = (unsigned char *)memcpy((char
*)&(dest->name),off,sizeof(dest->name));
printf("butt_to_struct()--ptr(dest-->name)...\n");
while( *ptr != 'o' )
printf("%c",*ptr++);
printf("%c\n",*ptr);

c-)Now to execute my task , i run 'Server.c' first and then 'Client.c'
from other
terminal. Now for the first time program runs fine. Then i terminate
both 'Server.c'
and 'Client.c' programs and when i run these two files again without
ever changing them
then 'Client.c' does execute but after the execution it prints 'Pipe
Broken' and exits. Now
Though 'Client.c' has executed but when i switch my terminal to see
whts going in 'Server.c' program
it is still waiting for a connection.
I mean this is absurd, why the heck program i.e 'Client.c' tells me
'Broken Pipe'
when being executed for the second time? This is beyond my
comprehension :(

d-) Last but not the least , in the main() of 'Server.c' when i
successfully
return from buff_to_struct() function and try to do the following
printf("Value of name = %s\n",s.name);
it prints
HelloBx
though it should have printed only 'Hello', now where these last two
bytes i.e. 'Bx'
came from ?
I know this must be time consuming for you, but im really stumped
about this so
i will really appreciate any kind of help. Thanks a lot for your
concern & time.....
Thanks in anticipation.

Regards....

There are many problems with these 2 programs, but see
my comments embedded in the following source code for
answers regarding your immediate questions....

Both 'Server.c' And 'Client.c' are attached below & im using gcc over
Red hat linux 8.0

Server.c
-----------
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>

typedef struct{
uint8_t a;
uint8_t b;
char name[5];
}str;

void buff_to_struct(str *dest, unsigned char *src){


unsigned char *off;
int len;
len =0;
off = src;


memcpy( &(dest->a), off, sizeof(dest->a));

off += sizeof(dest->a);
char *ptr;

memcpy(&(dest->b),off,sizeof(dest->b));
off += sizeof(dest->b);
ptr = (unsigned char *)memcpy((char
*)&(dest->name),off,sizeof(dest->name));
printf("butt_to_struct()--ptr(dest-->name)...\n");
while( *ptr != 'o' )
printf("%c",*ptr++);
printf("%c\n",*ptr);




}
int main()

{
str s;
int fd;
printf("Size of str--ptr..%d\n",sizeof(str));
struct sockaddr_in server,client;

fd = socket(AF_INET,SOCK_STREAM,0);
server.sin_family = AF_INET;
server.sin_port =htons(1800);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(fd, (struct sockaddr *)&server,sizeof(server));
listen(fd,2);
printf("Listening to Connetions...\n");

int len;
len = sizeof(client);
int connfd;
connfd = accept(fd, (struct sockaddr*)&client, &len);

unsigned char src[7];
int readlen ;
read(connfd,src,7);


buff_to_struct(&s,src);


printf("Value received(s.a)---=%d\n",s.a);
printf("Value of s.b =%d\n",s.b);
//Problem lies in the following, it *must* print 'Hello' but following
//line prints 'HelloBx' , why??????

Because the "%s" in the printf() format string tells printf() to
print a nul-terminated string, but s.name is NOT nul-terminated.
s.name[] is 5 bytes in size and contains 'h', 'e', 'l', 'l', 'o'.
This is NOT a nul-terminated string - there is no trailing '\0'.
Either use "%5.5s" in the printf() format string, or change the size
of 'name' in the definition of 'str' to be 6 bytes and then ALWAYS
write a nul byte to name[5] AS THE LAST WRITE operation before sending
it (e.g. copy bytes to 'name', THEN write a '\0' to name[5]).
printf("Value of name = %s\n",s.name);
printf("\n");

close(fd);
return 0;
}









________________________________________________________________________________________
Client.c
---------
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

typedef struct{
uint8_t a;
uint8_t b;
char name[5];

}str;

int parse_struct(unsigned char *dest,str *s){

unsigned char *off;
off = dest;

memcpy(off,(void *)&(s->a),sizeof(s->a));

off += sizeof(s->a);
memcpy(off,(void *)&(s->b),sizeof(s->b));

off += sizeof(s->b);
char *ptr;

ptr = (char *)memcpy(off,(void *)&s->name,sizeof(s->name));
//Purpose of following 'while' is to check the contents of 'off'
while (*ptr !='o')
printf("%c",*ptr++);
printf("%c\n",*ptr);
//Aforementioned while correctly prints the value of 'ptr'
printf("(Parse_struct) off=%s\n",off);

off += sizeof(s->name);
char ch='\0';
memcpy(off,(void *)& ch, sizeof(ch));

The above memcpy() writes the nul byte (ch) PAST THE END
of dest[] (i.e. to dest[7], which is the 8th byte in dest[],
but dest[] IS ONLY 7 BYTES LONG). You're lucky that it
doesn't overwrite something important.
So, when main() writes dest[] (aka buff[] in main) to the
socket, the nul byte (ch) is NOT written - because it's
not in buff[].
If 's' has 7 bytes of data, and you wish to follow it with
a nul byte when it is copied to dest[], then dest[] must be
at least one byte larger (i.e. dest[] must be 8 bytes)
int len ;
len = sizeof(s->a)+sizeof(s->b)+sizeof(s->name);
return len;

}
int main(){

str s;
s.a = 10;
s.b = 20;
strcpy(s.name,"Hello");


int fd;
struct sockaddr_in client;
fd = socket(AF_INET,SOCK_STREAM,0);
client.sin_family = AF_INET;
client.sin_port = htons(1800);
client.sin_addr.s_addr = inet_addr("127.0.0.1");



connect(fd,(struct sockaddr*)&client,sizeof(client));


printf("Connected and Writing data...\n");

unsigned char buff[7];

The above should be 'unsigned char buff[8];'.
int len;
len = parse_struct(buff,&s);

write(fd,buff,len);


exit(0);

}

Regards,
Larry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,735
Latest member
HikmatRamazanov

Latest Threads

Top