如何获取 Linux 上异步套接字上可读取的字节数?

问题描述 投票:0回答:1

我有一个在 Linux 上用 C++ 编写的简单 tcp/ip 服务器。我正在使用异步套接字和 epoll。当我收到 EPOLLIN 事件时,是否可以找出有多少字节可供读取?

c++ linux sockets asyncsocket
1个回答
9
投票

来自

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.