Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

read and write over tcp/ip sockets 1

Status
Not open for further replies.

ezeke1

Programmer
Mar 20, 2003
41
US
Hello All,
I'm trying to create a distributed system using a tcp server/client model and I'm having trouble getting the clients and server to talk. The main communication protocol is to pass message structures over a connected socket but it appears the data is getting garbled after a write() function call.
I've tried converting to network byte (htonl)order before sending and converting it back (ntohl) when receiving but that doesn't appear to help.
The structure I'm passing is fairly simple, it contains 3 integers and a character array. After some debugging, I think it might be the way I copy the data upon receiving it and I'm hoping someone can help me understand what I am doing wrong.

Thanks, David

The structure looks like this:
struct {
int size;
int id;
char name[128]
} _struct

I'm sending the structure like this:
send(socket, &_struct, sizeof(_struct));

and inside my receive function, I read the data like this:
_struct inc_struct;

read(socket, &inc_struct, sizeof(_struct));
..
..
// print out the data
printf("id is %d\n", inc_struct.id);
..
..
 
> I've tried converting to network byte (htonl)order before sending and converting it back (ntohl) when receiving but that doesn't appear to help.
You will need to do this if you want the process to be usable across many machine types.

> read(socket, &inc_struct, sizeof(_struct));
ALWAYS check the return result - packet reassembly is your problem in a TCP connection.
There is not a 1:1 correspondence between the packets you send and the packets you receive.

It's a good idea to prefix each new message with either a message length (or an identifier which can be used to derive a length).

--
 
>ALWAYS check the return result - packet reassembly is >your problem in a TCP connection.
>There is not a 1:1 correspondence between the packets you >send and the packets you receive.
That would explain why the data is garbled. I'm just not sure how read the incoming data and reconstruct the message.

>It's a good idea to prefix each new message with either a >message length (or an identifier which can be used to >derive a length).
Before sending the message structure, I actually send a character buffer that includes the size of incoming message. I was able to do a 1:1 copy of the buffer which led me to believe I could do the same with a multibyte structure.

Thanks, David
 
A bit like this
Code:
bytes_expected = 10;
bytes_received = 0;
while ( (n=read(socket, &buff[bytes_received], bytes_expected)) > 0 ) {
    bytes_received += n;
    bytes_expected -= n;
}

--
 
Thank you Salem. I really appreciate your input and time on this problem.

Your code will ensure the program reads in the correct size of the message. In my case, the structure I wrote earlier has 9 bytes. That solves the problem of making sure I receive the correct length of the message. But with this information, how do I reconstruct the data read?

Ok if I create a new struct called inc_msg of type _struct, can I just copy the data read into this structure?
Lets say the first read produces n=4 bytes. That's the size of an integer so can I copy this into a inc_msg.size.
Then for the next read, n=4 and I copy this into inc_msg.id and the last read produces n=1. I would then set 'inc_msg.name = n;' for this last byte?

David
 
> can I just copy the data read into this structure?
That's pretty much it.
Just read sizeof(struct) into a message buffer, then memcpy() it across to your real structure.

Though to be perfectly honest, you shouldn't use a structure for network data. Just because sizeof(mystruct) on your machine is say 9 bytes doesn't mean all machines would have the same size. Compilers are free to add padding bytes for memory alignment and such like.

Your 2nd suggestion hints at the better long-term approach.
Code:
memcpy( &mystruct.size, &buff[0], 4 );
memcpy( &mystruct.id,   &buff[4], 4 );
memcpy( &mystruct.ch,   &buff[8], 1 );

--
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top