I ran into a little issue with transferring data over (TCP) sockets. Small background on what I am doing:
I am sending data from side A to B. Data sent can be of variable lengths, assuming max size to be of 1096 bytes.
A) send(clientFd, buffer, size, NULL)
on B, since I dont know what size to expect, I always try to receive 1096 bytes:
B) int receivedBytes = receive(fd, msgBuff, 1096, NULL)
However, when I did this: I realized A was sending small chunks of data..say around 80-90 bytes. After a few bursts of sending, B was clubbing them together to have receivedBytes to be 1096. This obviously corrupted data and hell broke loose.
To fix this, I broke my data in two parts: header and data.
struct IpcMsg
{
long msgType;
int devId;
uint32_t senderId;
uint16_t size;
uint8_t value[IPC_VALUES_SIZE];
};
On A side:
A) send(clientFd, buffer, size, NULL)
on B, I first receive the header and determine the size of payload to receive: and then receive the rest of the payload.
B) int receivedBytes = receive(fd, msgBuff, sizeof(IpcMsg) - sizeof( ((IpcMsg*)0)->value ), 0);
int sizeToPoll = ((IpcMsg*)buffer)->size;
printf("Size to poll: %d\n", sizeToPoll);
if (sizeToPoll != 0)
{
bytesRead = recv(clientFd, buffer + receivedBytes, sizeToPoll, 0);
}
So, for every send which has a payload, I end up calling receive twice. This worked for me, but I was wondering if there is a better way of doing this ?
recv
to receive all data. – Gehennarecv
, but on a modern computer the performance penalty for multiplesend
/recv
calls is negligible (and TCP will probably put the data from two consecutivesend
calls in a single packet anyway). – Gehennasend the actual data size in a fixed size header
- I will have to make 2 send calls - a. header (as you suggested) and b. actual data ? – Palrecv
call. You can either use a smallheader
which holds "how long is the next part", and then receive until you've got it all. Or put a "marker" in your data to indicate "the end of data", (-1, 0, 0xDEADDEAD or something else that is not valid data). Either way, your receiving code needs to understand what you are sending, and where it is in the sequence. – Ruselsend
calls will not introduce any network "lag", as data from both calls will be sent as a single packet (if the amount of data is less than the MTU). And if the data is sent as a single packet, it doesn't matter how manyrecv
calls you make, it will still read from the single packet. – Gehennasendmsg()
function. – Nazler