我在Linux上用c ++编写了一个简单的tcp / ip服务器。我正在使用异步套接字和epoll。当我收到EPOLLIN事件时,是否可以找出可供读取的字节数?
答案 0 :(得分:7)
来自man 7 tcp
:
int value;
error = ioctl(sock, FIONREAD, &value);
或SIOCINQ
,FIONREAD
的同义词。
无论如何,我建议只在循环中以非阻塞模式使用recv
,直到它返回EWOULDBLOCK
。
<强>更新强>
根据您的评论,我认为这不适合您的问题。
想象一下,你的标题是8个字节,你只收到4个字节;然后,您的poll/select
将返回EPOLLIN
,您将检查FIONREAD
,查看标头尚未完成,并获取更多字节。但是这些字节永远不会到达,所以每次调用EPOLLIN
时都会继续poll/select
,并且你有一个无操作的忙循环。也就是说,poll/select
是级别触发的。并非边缘触发功能也能解决您的问题。
最后,您可以更好地完成一些工作,为每个连接添加一个缓冲区,并将字节排队,直到您有足够的数据。它并不像看起来那么困难,它的效果要好得多。例如,类似的东西:
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);
}
每当你想得到一些字节:
void PrepareToRecv(ConnectionData *d, size_t size)
{
d->buffer.resize(size);
d->offset = 0;
d->pending = size;
}