3

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

4

1 回答 1

8

来自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;
}
于 2013-07-31T16:25:50.783 回答