Google Answers Logo
View Question
 
Q: UDP/Sockets programming in C ( Answered 5 out of 5 stars,   0 Comments )
Question  
Subject: UDP/Sockets programming in C
Category: Computers > Programming
Asked by: darsenault-ga
List Price: $15.00
Posted: 20 Oct 2002 16:45 PDT
Expires: 19 Nov 2002 15:45 PST
Question ID: 85631
I am trying to send some data over a socket using tcp. My question is
about how to format and structure that data. I've got to send
specifically: a 4-byte int, a second 4-byte int and a 3 char string.
The idea is to get this data in one message. I am not 'allowed' to
just convert it all to a string of characters.

I've been attempting to get this data into one place to send it as:
[    int_one   ][   int_two    ][  int_ascii  ]
     4 bytes        4 bytes        4 bytes (or 3?)
where;
int_one is my first integer value
int_two is my second integer value
int_ascii is the ASCII values for XXX (or any 3 char string)

(1) How do I get this data into ONE variable/array etc so it goes over
the network as a series of bytes, including the character data? (I was
thinking use memcpy to put all the data into an array?)

(2) How do get the data back out on the other end? Especially
converting the character data back to it's string form.

Thank you for saving my hide!
-David
Answer  
Subject: Re: UDP/Sockets programming in C
Answered By: davidmaymudes-ga on 20 Oct 2002 19:15 PDT
Rated:5 out of 5 stars
 
you can declare a structure to hold the things you need to send....

struct _stuff {
    int int_one;
    int int_two;
    char ascii[4];  // or [3] if you don't want to send a terminating
null]
} s;

then, one complication as you're filling in the structure has to do
with big-endian vs. little-endian computers, i.e. if you're sending
your data from a macintosh to an intel computer.  you use the
functions htonl() and ntohl(), read as "host to network long" and
"network to host long" to convert to the "standard" format for the
network.  (further discussion at
http://telecom.vub.ac.be/sockprog/endian.htm, if you're interested.)

so, to send your data....
s.int_one = htonl(int_one);
s.int_two = htonl(int_two);
s.ascii[0] = first_char;
s.ascii[1] = second_char;
s.ascii[2] = third_char;
s.ascii[3] = '\0';    // null terminate the string, if you want....
send(sock, (char *) &s, sizeof(s));

and when you're receiving, it's pretty similar....
recv(sock, (char *) &s, sizeof(s), flags);
int_one = ntohl(s.int_one);
int_two = ntohl(s.int_two);

assuming that you've done the null-terminated version of the
structure, the characters in the structure make a perfectly good
string....  so you could just write

char my_string[4];
strcpy(my_string, s.ascii);

but this wouldn't really be a good idea, because then if the data
you're receiving *didn't* happen to have a zero in the last byte of
s.ascii[3], you'd run off the end of your structure and something
random would happen.  (important rule of network programming: never
trust any data you get over the network!)

so it might be better to at least check that the string was properly
null-terminated, or at least to use a length-limited routine like

strncpy(my_string, s.ascii, 4);

I hope this explanation makes sense; if you have further questions,
feel free to ask for a clarification....

Thanks,
David

Request for Answer Clarification by darsenault-ga on 20 Oct 2002 19:35 PDT
This look great. Thank you. This helps. One thing I'm unclear on is on
the recv side of things. Is the struct actually recv'd or does the
buffer just contain the bytes? It seems here that the struct is
maintained as sent.

You wrote:
and when you're receiving, it's pretty similar.... 
recv(sock, (char *) &s, sizeof(s), flags); 
int_one = ntohl(s.int_one); 
int_two = ntohl(s.int_two); 

The s.int_one and s.int_two references actually read the right # of
bytes from the buffer? Do I need to declare a struct on the recv side?
(It seems not.)

You have really helped me a TON! I think I'll be set with the
clarification above. Thank you so much.

-David
Do

Request for Answer Clarification by darsenault-ga on 20 Oct 2002 21:02 PDT
Just finished working with this code and it works VERY WELL. Thank you
sir. But does the cast (char *) &s in the line send(sock, (char *) &s,
sizeof(s), flags); send everything as char? or it all bytes?

Thanks again. You were a huge help. Excellent answer/code.
-David

Clarification of Answer by davidmaymudes-ga on 20 Oct 2002 21:16 PDT
when you call recv and pass a pointer and a length, the socket library
copies the number of bytes you asked for to whatever the pointer
points to.

so the recv() call copies twelve bytes into the structure (I was
assuming you're using the same variable to send and receive), and the
statement

int_one = ntohl(s.int_one);

copies the first four bytes out of that structure (possibly reversing
the byte ordering, if necessary) into your variable.


the key thing to remember is that in C, when you declare a structure,
you know how the elements of that structure will be laid out as a
sequence of bytes.

Clarification of Answer by davidmaymudes-ga on 20 Oct 2002 21:18 PDT
the (char *) part just tells the compiler that you want the memory
where the structure is to be "treated as" a sequence of bytes from the
point of view of the function you're calling.  the cast itself doesn't
make anything happen.

(In C++, casts can actually make code get executed, but not in C)

so the two numbers and the string are actually *already* laid out
properly into twelve bytes of memory by the act of copying them from
the separate variables into the structure.
darsenault-ga rated this answer:5 out of 5 stars
Simply outstanding answer. Direct and right in target. First class.

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy