Reputation: 4151
static void HandlePackets(void* pParams)
{
int iResult = 0;
char recvbuf[MAX_PACKET_LENGTH];
printf("Packet handling started\n");
while((iResult = recv(lhSocket, recvbuf, MAX_PACKET_LENGTH, 0)) > 0)
printf("Bytes received: %d\n", iResult);
printf("Packet handling stopped with reason %i", WSAGetLastError());
}
For now, it only prints the amount of bytes received.
Could such things happen, that recv
will receive only a half of packet? Or one full packet and half of next packet, if server sent them one by one fast?
For example, server sent a single packet with 512 bytes length, is it possible that recv first got 500 bytes, and the remain 12 will receive from second attempt?
If server sending a lot of packets with 512 bytes length for each, is it possible that recv
will get 700 bytes from first executing and the remain bytes from second?
MAX_PACKET_LENGTH
is 1024
(I talk here about application layer packets, not transport layer.)
The whole problem is - do I need to make some possibility for client to combine received bytes into one packet or split over-received bytes to different packets?
Upvotes: 4
Views: 4665
Reputation: 182893
Yes, with TCP, it can happen. But it's not a problem. If you receive too little, call receive again. If you receive too much, well that's great because it just saves you the trouble of having to call receive again.
The networking stack knows TCP, but it doesn't know the protocol you are implementing. If you want to divide the byte stream into messages, that's your job.
If you don't make the client do it, how will it possibly happen? The networking stack has no idea what your application layer packets are like. It has no idea what constitutes a complete application layer packet since it's not at the application layer.
Note that is the rule for TCP and other byte-stream protocols. Other protocols may have different semantics.
Upvotes: 4
Reputation: 9536
In TCP communication sender uses write()
(possibly in a loop) to send data. On the receiver side, read()
copies received data from a socket buffer into your buffer at application level. If one write() sends let's say 900 bytes, TCP can break it into multiple chunks of various sizes...e.g. 300, 400, and 200 bytes, so on the receiving side you need to call read()
three times in order to receive all data.
Now, if you put recv()
in a loop and each time it fills entire buffer or its part, how do you know when to stop receiving? When sender sends all data and gracefully closes connection, your recv()
will return 0
. There is nothing more to receive, you can close your socket.
I mentioned filling the buffer in a loop. If you're not processing data from receiving buffer in the recv()
loop, you need to preserve it somewhere, otherwise each iteration might overwrite it. (You can advance buffer pointer in each iteration but that would work only if you know in advance the length of the packet.) You can copy each received chunk into queue or some other data structure. Data processing usually goes in parallel with data receiving - and in another, processing thread.
But let's go back to recv()
loop. Apart from waiting for 0
, there is another trick of how can receiver know when to stop receiving: sender and receiver can agree (know) that e.g. first two bytes sent will carry the length of the message. So at the beginning, receiver will wait only for two bytes. Once it receives them, it will unpack the information on the message size, let's say 900 bytes. Now receiver can adjust its buffer size to 900 and receives in a loop until all 900 bytes are received. Each recv()
will return number of bytes received, and receiver can advance buffer pointer by that number of bytes so the next recv()
writes into free part of the buffer.
Btw, this shared knowledge (contract) between client and server (or receiver and sender) is your communication protocol at the application level. It comes on the top of TCP protocol.
Upvotes: 2
Reputation: 385405
Is it possible that
recv
first got 500 bytes, and the remain 12 will receive from second attempt?
Yes, definitely.
You have no guarantee that, when the sending end sends a burst of X bytes, that the receiving end will pick them all up in a single call to recv
. recv
doesn't even know how many bytes are in your application-layer "packet".
The whole problem is - do I need to make some possibility for client to combine received bytes into one packet or split over-received bytes to different packets?
Your application will definitely have to accumulate data from possibly sequential reads, fill up a buffer, and implement parsing to look for a full packet.
TCP/IP doesn't know your application's protocol; as David said, if you want to split the incoming data stream into "packets" then you must do that yourself.
Upvotes: 4