我如何获得可在linux上的异步套接字上读取的字节数?

Pav*_*dov 3 c++ sockets linux asyncsocket

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

rod*_*igo 8

来自man 7 tcp:

int value;
error = ioctl(sock, FIONREAD, &value);
Run Code Online (Sandbox Code Playgroud)

或者,也就是说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);
}
Run Code Online (Sandbox Code Playgroud)

每当你想获得一些字节时:

void PrepareToRecv(ConnectionData *d, size_t size)
{
    d->buffer.resize(size);
    d->offset = 0;
    d->pending = size;
}
Run Code Online (Sandbox Code Playgroud)