stupid winsock send() question

Started by
7 comments, last by wing_majin 20 years, 8 months ago
Can anyone tell me why when I call consecutive send()s the corresponding receiving methods seem to clump the data together? I shall illustrate by example: I have a client that connects to a multi-threaded server (a client connects, a thread is produced to handle it blah blah...) and upon connection uses a few send()s to send what I need. Most of the time this works fine. That is, the received data after say, 3 send()s will be 3 separate strings. However sometimes (oddly) the strings sent to the server by those consecutive send()s mash together to form one string. Something like this: CLIENT: send(socket, "string one", 10, 0); send(socket, "two string 2", 12, 0); Server receives: (recv() is in a loop, one call per iteration) "strintwo" (or something else similar) I reduced the occurance rate of this by slapping some Sleep() functions in just for the hell of it, but it still occured sometimes nonetheless. This led me to believe that send() wasn''t waiting for the previous call to finish before it sent again and the network traffic had some effect. Also, the sends are always called from the same thread, like I show above, and are received one by one in the server, so this couldn''t be a problem I assume. I should be able to just send() all day till I pass out, regardless of the network or system state right? I can''t help but think there''s a really easy solution to this, and hence, I label it "stupid winsock send() question".
Advertisement
If you are using TCP, then you have a stream, and the network layer may clump/chop your data into any pieces it sees fit.

To do messages over TCP, you have to precede each message with length information. Like so:

void sendString( char const * str, int sock )
{
int ch = strlen( str );
assert( ch < 256 );
if( ch > 255 ) ch = 255;
unsigned char len = (unsigned char)ch;
send( sock, &len, 1 );
send( sock, str, len );
}

void readString( int sock, char buf[ 256 ] )
{
unsigned char len;
if( 1 != recv( sock, &len, 1 ) ) {
error();
}
if( len != recv( sock, buf, len ) ) {
error();
}
buf[len] = 0;
}
If "string one" and "two string 2" become "string onetwo string 2", then this is the expected behaviour: TCP sockets represent a stream of data. It''s up to the receiver to break up the data.
Consider sending the length of the data before the actual data.
I''m sorry, for some reason I thought it wasn''t sending it that way Beer Hunter. But it is just combining them. So if I just send length information, then the actual data, then test for the length, and receive the actual length and then receive the correctly sized data, that should split them up properly? However what''s to prevent the length information from being grouped with the proceeding respective data it describes? If I was to use the anonymous poster''s function wouldn''t those two send()s just get clumped as well? A message: "testing" that would be send as:
send(sock, "7", 1);
send(sock, "testing", 7);
would still just create: "7testing" then wouldn''t it?
If you know that the length only takes up one character, then you can just recv() that one character before the rest of the data.
I''d probably use two bytes for the length, though.
It is not a better idea to divide messages with CRLF or something?
I was thinking too much on the send side. I realize that if the length of any message is included somehow then it''ll just be received however and the result is to be parsed out accordingly.
Using CRLF or just \n or any separation char would be fine for just sending multiple messages at once. However sometimes a send() is conditional or there are other reasons separate calls need to be made (can''t think of any right now).
You can''t structure it so you rely on how the data comes in. It could come in in 1 byte segments one after another if things got really bad, and you have to be able to handle this gracefully.

To reply to your original post, that shouldn''t happen. I really hope you''re checking return values here, because TCP is designed to guard against receiving data out of order.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
Use a fixed size packet header. Whenever you send something you send the header ahead of it which has how many bytes to be expecting. On the client side you read only the header first then loop the recv until you get x bytes mentioned in the header. tcp/ip sockets are guaranteed to send, but not all at once. You can ensure that a whole packet is sent/recvd at once by looping your send/recv functions until you get the appropriate number of bytes returned. If you need more of an explaination or an example of what I mean, e-mail me at jessechoward@netscape.net
Evillive2

This topic is closed to new replies.

Advertisement