An option with delimiters in length is probably the best. This allows you to be smart about the allocation of buffers on the receiving side and allows you to send messages containing any character you want. It also eliminates the need to carefully examine each character to see if you have reached the end of the message. Unfortunately, it is very easy to implement this badly.
I will provide you with good code that will do it right.
On the receiver side:
unsigned char lenbuf[4]; // This whole thing with the while loop occurs twice here, should probably // have its own function. { bytesRead = 0; while (bytesRead < 4) { //read as much as we can. note: byteInc may not == len-bytesRead. int byteInc = recv(socket, &lenbuf[bytesRead], 4-bytesRead, 0); if(byteInc != SOCKET_ERROR) { bytesRead += byteInc; } else { //should probably handle this error properly break; } } } // end scope for bytesRead unsigned int len = ((lenbuf[0] & 0xffu) << 24) | ((lenbuf[1] & 0xffu) << 16) | ((lenbuf[2] & 0xffu) << 8) | (lenbuf[3] & 0xffu); ::std::vector<char> buffer; buffer.resize(len); { unsigned int bytesRead = 0; while(bytesRead < len) { //read as much as we can. note: byteInc may not == len-bytesRead. int byteInc = recv(socket, &buffer[bytesRead], len-bytesRead, 0); if(byteInc != SOCKET_ERROR) { bytesRead += byteInc; } else { //should probably handle this error properly break; } } //buffer now contains the complete message. some_processing_function(buffer); }
On the sending side:
const unsigned char lenbuf[4] = { ((bytesToSend >> 24) & 0xffu), ((bytesToSend >> 16) & 0xffu), ((bytesToSend >> 8) & 0xffu), (bytesToSend & 0xffu) }; // This basic block is repeated twice and should be in a function { unsigned int bytesSent = 0; while (bytesSend < 4) { const int sentNow = send(socket, &lenbuf[bytesSent], 4-bytesSent, 0); if (sentNow != SOCKET_ERROR) { bytesSent += sentNow; } else { // Should handle this error somehow. break; } } } { unsigned int bytesSent = 0; while (bytesSent < bytesToSend) { const unsigned int toSend = bytesToSend - bytesSent; const int sentNow = send(socket, &byteBuf[bytesSent], toSend, 0); if (sentNow != SOCKET_ERROR) { bytesSent += sentNow; } else { // Should handle this error somehow. break; } } }
The main problem that the other code left is that it doesnβt handle things very well if you get only part of the length, and not all. Needless to say, the information will not be shared so that things will be divided in the middle of the length information.
Another problem is that the length is sent in such a way that the processor and compiler are not agnostic. Different types of processors and different C ++ compilers store their integers in different ways. If the compiler / CPU combination used by the sender is different from the compiler / CPU combination used by the receiver, this will cause problems.
Thus, explicitly excluding an integer into platform symbols in a neutral way and re-combining it again is the best way.