我有一个在Linux上用c++编写的简单tcp/ip服务器。我使用异步套接字和epoll。当我收到EPOLLIN事件时,是否可以找出有多少字节可供阅读?
qq24tv8q1#
从man 7 tcp:
man 7 tcp
int value; error = ioctl(sock, FIONREAD, &value);
字符串或者SIOCINQ,它是FIONREAD的同义词。无论如何,我建议在循环中以非阻塞模式使用recv,直到它返回EWOULDBLOCK。
SIOCINQ
FIONREAD
recv
EWOULDBLOCK
更新:
从你下面的评论中,我认为这不是解决你问题的合适方法。假设你的头是8个字节,而你只收到4个字节;然后你的poll/select将返回EPOLLIN,你将检查FIONREAD,看到头部还没有完成,并等待更多的字节。但这些字节永远不会到达,所以你继续在每次调用poll/select时获得EPOLLIN,你有一个无操作的忙循环。也就是说,poll/select是 * 电平触发的 *。并不是说边沿触发函数也能解决你的问题。最后,你最好做一些工作,为每个连接添加一个缓冲区,并将字节排队,直到你有足够的字节。这并不像看起来那么困难,而且效果更好。例如,类似这样的事情:
poll/select
EPOLLIN
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; }
型
1条答案
按热度按时间qq24tv8q1#
从
man 7 tcp
:字符串
或者
SIOCINQ
,它是FIONREAD
的同义词。无论如何,我建议在循环中以非阻塞模式使用
recv
,直到它返回EWOULDBLOCK
。更新:
从你下面的评论中,我认为这不是解决你问题的合适方法。
假设你的头是8个字节,而你只收到4个字节;然后你的
poll/select
将返回EPOLLIN
,你将检查FIONREAD
,看到头部还没有完成,并等待更多的字节。但这些字节永远不会到达,所以你继续在每次调用poll/select
时获得EPOLLIN
,你有一个无操作的忙循环。也就是说,poll/select
是 * 电平触发的 *。并不是说边沿触发函数也能解决你的问题。最后,你最好做一些工作,为每个连接添加一个缓冲区,并将字节排队,直到你有足够的字节。这并不像看起来那么困难,而且效果更好。例如,类似这样的事情:
型
每当你想得到一个字节数时:
型