Issue
I have a simple tcp/ip server written in c++ on linux. I'm using asynchronous sockets and epoll. Is it possible to find out how many bytes are available for reading, when i get the EPOLLIN event?
Solution
From man 7 tcp
:
int value;
error = ioctl(sock, FIONREAD, &value);
Or alternatively SIOCINQ
, which is a synonym of FIONREAD
.
Anyway, I'd recommend just to use recv
in non-blocking mode in a loop until it returns EWOULDBLOCK
.
UPDATE:
From your comments below I think that this is not the appropriate solution for your problem.
Imagine that your header is 8 bytes and you receive just 4; then your poll/select
will return EPOLLIN
, you will check the FIONREAD
, see that the header is not yet complete and wait for more bytes. But these bytes never arrive, so you keep on getting EPOLLIN
on every call to poll/select
and you have a no-op busy-loop. That is, poll/select
are level-triggered. Not that an edge triggered function solves your problem either.
At the end you are far better doing a bit of work, adding a buffer per connection, and queuing the bytes until you have enough. It is not as difficult as it seems and it works far better. For example, something like that:
struct ConnectionData
{
int sck;
std::vector<uint8_t> buffer;
size_t offset, pending;
};
void OnPollIn(ConnectionData *d)
{
int res = recv(d->sck, d->buffer.data() + offset, d->pending);
if (res < 0)
handle_error();
d->offset += res;
d->pending -= res;
if (d->pending == 0)
DoSomethingUseful(d);
}
And whenever you want to get a number of bytes:
void PrepareToRecv(ConnectionData *d, size_t size)
{
d->buffer.resize(size);
d->offset = 0;
d->pending = size;
}
Answered By - rodrigo Answer Checked By - Terry (WPSolving Volunteer)