Winsock udp recv not receiving all data even within a loop - c++

I have some UDP recv code utilizing winsock, specifically AF_INET, SOCK_DGRAM, and IPPROTO_UDP. The recv call exists in a loop that reads until all data is received. The problem is that I only get partial data every time. Furthermore I shouldn't even need the loop since I can see that all the data exists in a single packet. In wireshark I see that the real data length is 299 bytes. Wireshark successfully sees the entire packet so I know the packet sender is working correctly.
With my windows UDP code I only get 8 bytes until my receive method returns. I can see that the UDP code is stopping when it sees a 00 byte. Wireshark is able to read past those 00 bytes but windows udp recv is not able to read past it. It seems like windows sees the 00 as the end and therefore concludes that the packet is only 8 bytes.
I have looked at the header in wireshark and I see that the length specified is correct so i'm very confused as to why its only reading 8 bytes. Thank you for your help in advance.
This is what my receive call looks like for reference:
int ret = recv(socket, buffer, 1500, 0);
ret becomes 8 and buffer, which has been allocated to be 1500 bytes, is only filled with 8 bytes

UDP is message-oriented, not stream-oriented like TCP is.
In UDP, the only way that recv() would return 8 bytes is if either:
you set the len parameter to > 8, and a datagram containing exactly 8 bytes is received.
you set the len parameter to == 8, and a datagram containing more than 8 bytes is received.
Given your claim that that you are setting the len to 1500, then the only possibility is that the datagram received only has 8 bytes in it, not 299 bytes like you claim.
Unlike in TCP, in UDP you cannot read a datagram in pieces, a read is an all-or-nothing operation (unless you peek the data, which you are not doing). In UDP, recv()/recvfrom() reads whole datagrams at a time, and if the provided buffer is too small to receive the data (which it is not in this case) then an WSAEMSGSIZE error is reported and the data is truncated, discarding the rest of the data that does not fit in the buffer.
The 00 null bytes you describe have NO EFFECT WHATEVER on recv()/recvfrom()'s ability to read a whole datagram. A datagram carries a payload length, and recv()/recvfrom() will read up to that payload length or the specified buffer size, whichever is smaller, regardless of the actual payload content.
So, chances are, in your code, recv() is simply not receiving the datagram you are expecting.
For instance, in order to use recv() in UDP at all, you must connect() the UDP socket first to associate it with a specific peer IP/port, thus allowing recv() to ignore inbound datagrams from other peers (and for send() to send datagrams to a specific peer). Maybe you are connect'ing your UDP socket to the wrong peer, and thus reading datagrams that are meant for something else. Or, maybe you are connect'ing to the correct peer and it really is sending an 8-byte datagram that you are not expecting.
Since you did not provide any context info about your setup, the peer involved, the protocol involved, the Wireshark capture, nothing, there is really no way for anyone here to diagnose your situation with any certainty. But, what I described above would account for the symptom you have described. If you feel that is not the case, then you need to edit your question to provide more details.

Related

recv() with MSG_PEEK shows full message but returns 'would block' normally

I have a non-blocking winsock socket that is recv'ing data in a loop.
I noticed that when connecting with, say, putty and a raw socket, sending messages works just fine. However, when interfacing with this particular client, the packets seem to not be triggering a successful, non-MSG_PEEK call to recv. I recall having a similar issue a few years back and it ended up having to end the packets in \r or something coming from the client, which isn't possible in this case since I cannot modify the client.
Wireshark shows the packets coming through just fine; my server program, however, isn't working quite right.
How would I fix this?
EDIT: Turning the buffer size down to, say, 8 resulted in a few successful calls to recv without MSG_PEEK.
Recv call:
iLen = recv(group->clpClients[cell]->_sock, // I normally call without MSG_PEEK
group->clpClients[cell]->_cBuff, CAPS_CLIENT_BUFFER_SIZE, MSG_PEEK);
if(iLen != SOCKET_ERROR)
{
...
Socket is AF_INET, SOCK_STREAM and IPPROTO_TCP.
Use setsockopt to set TCP_NODELAY to TRUE.
Microsoft documentation states in several places that MSG_PEEK should be avoided altogether because it is inefficient and inaccurate. Use select(), WSAAsyncSelect(), or WSASelectEvent() instead to detect when a socket has data available for reading, then call recv() or WSARecv() to actually read it.
TCP socket is a stream of bytes, it does not preserve your application message boundaries. As soon as kernel has something to give to you, it returns from the poll. You have to collect received bytes until you have enough to decode whatever you need to decode.
The solution ended up being implementation-specific; I knew the length of all packets coming from the client were divisible by a certain amount of bytes. So, I just read that amount of bytes until the buffer was empty.
The max. number of bytes you can receive at a time in this situation must be less than the maximum length of the longest message, and must be the GCF (Greatest Common Factor) of that length.
This is far from a permanent solution, but it works for now.

C++ winsock recvfrom() and sendto()

I have a client application using winsock's sendto() method to send data to a server application with UDP. On my client application I make, say, 5 quick sendto(). On my server application, I wait for, say, 10 secs, and then do a select() and recvfrom(). Will the recvfrom() give me the first packet sent by the client or will it be an arbitrary one (whichever one arrived first)? Will I still be able to get the other 4 data packets or does winsock's UDP framework only buffer one?
Will the recvfrom() give me the first packet sent by the client or
will it be an arbitrary one
Since UDP doesn't handle reordering, you can get any of the messages. You could get less than 4 messages or even more (but that's rare today).
UDP gives no guarantee to the received ordering of packets, so basically, the first packet you recvfrom() might be the first packet you sent, but must not be - that's what TCP is for (which guarantees ordering of received data). You might not receive a part of the packets (or any, for that matter) at all if they were lost in transit.
For the second part: generally, the operating system will buffer a certain amount of packets for you, this depends on the socket buffer set up for UDP sockets - the buffer is specific to every socket, and not shared between them. On Windows, I'm not sure at how to get at the size of the buffer, on Linux, check out "/proc/sys/net/ipv4/udp_mem"; generally, you'll easily fit five UDP packets in there.
With 5 packets of reasonable size, you will probably get all of the packets and you will probably get the first one sent first. But they might be out of order, might not arrive, and might not contain the original data if they do arrive. You have to handle all of that yourself with UDP. (But depending on your application and requirements and the stability of your network, it might not be a real problem; it is certainly possible for certain situations to exist where receiving 99% of the data is perfectly fine).

How C++ `recv` function acts at data receving? Could it receive a partial "packet"?

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?
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.
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.
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.

How to receive more than 1440 through the socket

I wrote two simple programs server and a client using sockets in C++ (Linux). And initially it was a sample client-server application (echo-message sending and receiving the answer). Next, I changed the client in order to implement HTTP GET (now I do not use my sample server anymore). It works, but whatever buffer size I set, the client receives only 1440 bytes. I want to receive whole page into the buffer. I think that this is concerned with the TCP properties and I should implement some kind of cycle inside my client's code to capture all the parts of the answer. But I don't know what exactly I should do.
This is my code:
...
int bytesSent = send(sock, tmpCharArr, message.size()+1, 0);
// Wait for the answer. Receive it into the buffer defined.
int bytesRecieved = recv(sock, resultBuf, 2048*100, 0);
...
2048*100 is a buffer size and I think this is more than enough for the relatively small WEB-page used for testing. But as I mentioned, I receive only 1440 bytes.
What can I do with recv() function call to capture all the reply "parts" when the server's response is larger then 1440 bytes?
Thanks in advance.
The buffer size is determined by factors outside your control (routers, ADSL links, IP stacks, etc.). The standard way to transmit large volumes of data is to call recv() repeatedly.
HTTP works over TCP, and to understand the working of TCP sockets better you have to think of them as a stream rather than packets.
For further clarity, read my earlier post: recombine split TCP packet with flash sockets
As to why you receive only 1400 (or so) bytes, you have to understand MTU and Fragmentation. To sum it up, MTU (Maximum Transmission Unit) is the ability of the network to transfer a single packet of a certain maximum size. MTU of a entire network is the lowest MTU of all the routers involved. Fragmentation is splitting up of the packets if you try to send a single packet of size larger than the MTU of that network.
For a better understanding of MTU and Fragmentation, read: http://www.miislita.com/internet-engineering/ip-packet-fragmentation-tutorial.pdf
Now as for how to receive the entire page in the buffer, one alternative is to keep calling recv() and appending the data you get in a buffer, until recv() returns zero. This will work because typically a web-server will close the TCP connection after it sends you the response. However, this technique will fail to work if the web-server doesn't close the session (maybe keep-alives are configures).
Therefore, the correct solution would be to keep receiving until you have received the HTTP header. Take a peek and determine the length of the entire HTTP response (Content-Length:) and then you can keep on receiving until you have received the exact amount of bytes you were supposed to receive.

Confusion about UDP/IP and sendto/recvfrom return values

I'm working with UDP sockets in C++ for the first time, and I'm not sure I understand how they work. I know that sendto/recvfrom and send/recv normally return the number of bytes actually sent or received. I've heard this value can be arbitrarily small (but at least 1), and depends on how much data is in the socket's buffer (when reading) or how much free space is left in the buffer (when writing).
If sendto and recvfrom only guarantee that 1 byte will be sent or received at a time, and datagrams can be received out of order, how can any UDP protocol remain coherent? Doesn't this imply that the bytes in a message can be arbitrarily shuffled when I receive them? Is there a way to guarantee that a message gets sent or received all at once?
It's a little stronger than that. UDP does deliver a full package; the buffer size can be arbitrarily small, but it has to include all the data sent in the packet. But there's also a size limit: if you want to send a lot of data, you have to break it into packets and be able to reassemble them yourself. It's also no guaranteed delivery, so you have to check to make sure everything comes through.
But since you can implement all of TCP with UDP, it has to be possible.
usually, what you do with UDP is you make small packets that are discrete.
Metaphorically, think of UDP like sending postcards and TCP like making a phone call. When you send a postcard, you have no guarantee of delivery, so you need to do something like have an acknowledgement come back. With a phone call, you know the connection exists, and you hear the answers right away.
Actually you can send a UDP datagram of 0 bytes length. All that gets sent is the IP and UDP headers. The UDP recvfrom() on the other side will return with a length of 0. Unlike TCP this does not mean that the peer closed the connection because with UDP there is no "connection".
No. With sendto you send out packets, which can contain down to a single byte.
If you send 10 bytes as a single sendto call, these 10 bytes get sent into a single packet, which will be received coherent as you would expect.
Of course, if you decide to send those 10 bytes one by one, each of them with a sendto call, then indeed you send and receive 10 different packets (each one containing 1 byte), and they could be in arbitrary order.
It's similar to sending a book via postal service. You can package the book as a whole into a single box, or tear down every page and send each one as an individual letter. In the first case, the package is bulkier but you receive the book as a single, ordered entity. In the latter, each package is very light, but good luck reading that ;)
I have a client program that uses a blocking select (NULL timeout parameter) in a thread dedicated to waiting for incoming data on a UDP socket. Even though it is blocking, the select would sometimes return with an indication that the single read descriptor was "ready". A subsequent recvfrom returned 0.
After some experimentation, I have found that on Windows at least, sending a UDP packet to a port on a host that's not expecting it can result in a subsequent recvfrom getting 0 bytes. I suspect some kind of rejection notice might be coming from the other end. I now use this as a reminder that I've forgotten to start the process on the server that looks for the client's incoming traffic.
BTW, if I instead "sendto" a valid but unused IP address, then the select does not return a ready status and blocks as expected. I've also found that blocking vs. non-blocking sockets makes no difference.