I'm trying to write a simple TCP server in C++ using sockets. I wanted to create a function that would read the incoming packet to a std::string
with the exact size, but in order to do this, I need to know the exact size of the incoming packet:
int Socket::Read(int sockfd, std::string& string)
{
/* How can I get the size of the incoming packet before calling recv? */
return 0;
}
How can I get the exact size of an incoming packet before receiving it and writing it into a buffer in C/C++?
There is no such thing, whatsoever, that's called a "packet" when it comes to TCP sockets.
A TCP socket is an abstraction for a byte stream. Its inner mechanics are abstract, and it's simultaneously a source of arbitrary bytes that can arrive at any time, and a sink for bytes that can be written at any time, with the caveat that if the underlying transport determines that the write buffer is full the write()
or send()
will either return an indication that fewer bytes were written than specified by their third parameter, or they'll block until the peer reads from its socket and more bytes can be written to the socket.
It is a very common newbie error to assume that every write()
or send()
on a TCP socket on the sending side will be matched by a read()
or recv()
from a TCP socket on the receiving side. This is not true. The sender might write()
200 bytes, and the first read()
or recv()
will return the first 50 bytes, only, and the next call returns the remaining 150 bytes.
If a program does not diligently check the value returned by every read()
, recv()
, write()
, or send()
and explicitly handles every possible value, it's only a matter of time before that house of cards collapses into a pile of rubble.
It is true that the underlying transport layer, that shuffles the TCP socket's bytes between the sender and the receiver, handles that task in terms of discrete packets. However this is an internal implementation detail that is generally inaccessible from the TCP layer. You will need to restructre your program's logic so that it does not "need to know the exact size of the incoming packet", but rather treats the TCP socket as an emitter of a completely unstructured stream of bytes
It is true that on many socket stacks it's possible to determine the number of unread bytes on a socket, or a file descriptor, and have a guarantee that reading that many bytes won't block. But that still will not tell you anything useful, in terms of those mysterious entities called "packets". You might discover that your TCP socket has the same 200 unread bytes. And they still, in practice, arrived in two discrete packets of 50 and 150 bytes, and are sitting there, for your application to read them.