You are using TCP, which is a stream socket (SOCK_STREAM). The data is
not organized into fixed-length chunks, it's organized into a continuous
stream of data.
Just because the other end sent 1869 bytes does not (and SHOULD NOT)
mean that you will receive 1869 bytes when you call recv(). It means
that 1869 bytes have been sent from the other application to that other
computer's TCP/IP stack.
You might receive 500 bytes, then 1000 bytes, then 369 bytes. Or you
might receive 10 bytes, then 1859 bytes. Or you might receive any
other variation of calls that add up to 1869.
Furthermore, if the sender sends 1869 in one call, followed by 1000 in
the second call, it's possible that your application will receive 2869
in a single call to recv().
Don't write your application in a manner that expects data to arrive in
a fixed-length chunk. That's not how TCP was intended to work! Think
of the data as a continuous stream, depending on the speed of the
computer, how busy it is, how fast the network is, etc, you will receive
different lengths at different times. It's no big deal, just call
recv() in a loop until you get the total size you need.
If you really, really, want to force the TCP stream to only return data
when 1869 bytes are available, then you should set the SO_RCVLOWAT
socket option to 1869. But I discourage you from doing this, because
IMHO, it's not the right mindset. A stream socket (SOCK_STREAM) is just
that -- a continuous stream of data. It's not a record-oriented
service, don't treat it like a record-oriented service. Plus, if you
set SO_RCVLOWAT and the sender sends a shorter amount of data, you're
stuck blocking on that socket waiting for the rest of the data, which
isn't good either.
I strongly recommend that you design your TCP communications to use some
sort of a delimiter instead of using a fixed-length piece of data. Most
TCP applications use CRLF as a delimiter, so that the data appears on
the display like normal text, it makes it much easier to troubleshoot
your applications.
Alternately, send the length first, followed by the data, so that the
receiving side knows exactly how many bytes it can expect, and can loop
until it's received the whole thing. This is the way HTTP (and others)
transfer data so that no special delimiter character has to be chosen
(and therefore, no escaping of special characters is needed)
I wrote an article that demonstrates how to use a loop to receive a
fixed-length chunk of data from a stream socket. The following link
requires a membership to System iNetwork, but a free ("Associate")
membership will work fine:
http://www.systeminetwork.com/article.cfm?id=51985
GKern@xxxxxxxxxxxxxxxx wrote:
I have a socket server program. The client is sending 1869 bytes of data,
but the socket Read function only returns 1392 bytes, and on the
subsequent read it returns the remaining 477 bytes (1392+477=1869).
When I look at the TCP connection status via netstat *cnn I can see Bytes
In listed as 1869 but then paging down I see the Maximum Segment Size is
1392.
I've tried to use the set socket option for SO_RCVBUF to override the
number of bytes per socket read.
Funny thing is that if I disconnect the client, and re-issue the Socket
Accept to create a new socket, and then reconnect and resend the 1869
bytes, I get all 1869 bytes in one read. But then if I resend the same
data again it reverts back to the original problem (1392 bytes read first
time and subsequent 477 bytes read the second time).
How can I correct this so that I can in one read accept the entire string
of data sent by the client?
As an Amazon Associate we earn from qualifying purchases.