In you code here:
Code:
mystruct rcv_msg;
char buf[128];
int j;
j = read(socket, buf, sizeof(buf));
memcpy(&rcv_msg, buf, j);
... I don't see a direct relationship between buf and rcv_msg, as far as size goes. This could be a problem if sizeof(rcv_msg) isn't the same as sizeof(buf) (when you do the memcpy).
>>j = read(socket, buf, sizeof(buf));
The problem here is that you're never actually checking how much data you're getting from the read(). Just because you asked for sizeof(buf) bytes, doesn't mean you got it. The TCP/IP stack can give you chunks of data, depending on how it is receiving it from the network. It will of course, give you all the data in the correct order.
For example, if you send() a 4k block of data, the receiving end may have to issue a number of read() calls to get it all.
A safer way to do things, is to wrap the read() function inside your own function that will validate the amount of data it receives, prior to it being passed back to the core program. If you are dealing with fixed sized data structures, you might implement a wrapper function like so:
Code:
mystruct msg;
if (myread(socket, &msg, sizeof(msg)) != sizeof(msg))
{
/* Error receiving, close socket + return */
}
/* Good read, all data present...*/
----------------------------
int myread(int socket, void *buffer, size_t bufsize)
{
/* This function calls read as many times as necessary
to fill the buffer with the specified number of bytes.
It will only return when the buffer is full, or the
socket goes bad.
*/
}
Other common ways to do this, are to:
- use a delimiter, read() bytes one at a time until you get that magic character (buffering IO when you get more advanced).
- use a small header of fixed size on each message that denotes the length of the full message. For example, send 4 bytes that have value 1234, telling the receiver to expect 1234 bytes of data to follow. Again, multiple read()s may be necessary.
A common trap can also be to read() too much data. If you do that, you could end up with 2 messages inside your read buffer (or even partial messages), and you will need to split and join accordingly.