(十)Buffer

Buffer 处理数据输入,是非阻塞Tcp 网络编程中必不可少的东西;

1. Buffer

在这里插入图片描述
内部持有vector 保存缓存的数据,readerIndex_ 和 writerIndex_ 作用如上(prependable bytes 初始为8 字节);

在这里插入图片描述
retrieve 系列将buffer 中的可读数据提取,只有retrieveAsString 带来返回,其余类似忽略

void retrieveAll() {
        _readerIndex = kCheapPrepend;
        _writerIndex = kCheapPrepend;
    }

std::string retrieveAsString() {
        std::string str(peek(), readableBytes());
        retrieveAll();
        return str;
}

void retrieve(size_t len) {
        assert(len <= readableBytes());
        _readerIndex += len;
}

void retrieveUntil(const char *end) {
        assert(peek() <= end);
        assert(end <= beginWrite());
        retrieve(end - peek());
}

append 系列为buffer 添加数据

void append(const std::string &str) { append(str.data(), str.length()); }

void append(const char *data, size_t len) {
        ensureWriteableBytes(len);
        std::copy(data, data + len, beginWrite());
        hasWritten(len);
}

void append(const void *data, size_t len) {
        append(static_cast<const char *>(data), len);
}

void ensureWriteableBytes(size_t len) {
        if (writableBytes() < len) {
            makeSpace(len);
        }
        assert(writableBytes() >= len);
}

void makeSpace(size_t len) {
        if (writableBytes() + prependableBytes() < len + kCheapPrepend) {
            _buffer.resize(_writerIndex + len);
        } else {
            assert(kCheapPrepend < _readerIndex);
            size_t readable = readableBytes();
            std::copy(begin() + _readerIndex, begin() + _writerIndex,
                      begin() + kCheapPrepend);
            _readerIndex = kCheapPrepend;
            _writerIndex = _readerIndex + readable;
            assert(readable == readableBytes());
        }
}

添加数据先转换成char* 合适的格式,确保是否有足够的空间,没有则扩容(当前空余无用空间由prependable 和 writeable 组成若两者加起来不足则vector resize 扩容,而若可以,把readable 移动至最左端)

read 系统调用改成readv(允许单系统读入多个缓冲区),使用scatter / gather IO;

ssize_t Buffer::readFd(int fd, int *savedErrno) {
    char extrabuf[65536];
    struct iovec vec[2];
    const size_t writable = writableBytes();
    vec[0].iov_base = begin() + _writerIndex;
    vec[0].iov_len = writable;
    vec[1].iov_base = extrabuf;
    vec[1].iov_len = sizeof extrabuf;
    const ssize_t n = readv(fd, vec, 2);
    if (n < 0) {
        *savedErrno = errno;
    } else if (implicit_cast<size_t>(n) <= writable) {
        _writerIndex += n;
    } else {
        _writerIndex = _buffer.size();
        append(extrabuf, n - writable);
    }
    return n;
}

2. Channel

修改read 事件回调函数和相关设置

typedef std::function<void(Timestamp)> ReadEventCallback;
void handleEvent(Timestamp receiveTime);
void setReadCallback(const ReadEventCallback& cb);

3. TcpConnection

在成员变量中添加Buffer _inputBuffer
修改handleRead 中messageCallback 参数,receiveTime 由poll 提供;

void TcpConnection::handleRead(Timestamp receiveTime) {
    int savedErrno = 0;
    ssize_t n = _inputBuffer.readFd(_channel->fd(), &savedErrno);
    if (n > 0) {
        _messageCallback(shared_from_this(), &_inputBuffer, receiveTime);
    } else if (n == 0) {
        handleClose();
    } else {
        errno = savedErrno;
        LOG_SYSERR << "TcpConnection::handleRead";
        handleError();
    }
}
Timestamp Poller::poll(int timeoutMs, ChannelList *activeChannels) {
    LOG_TRACE << "before sys poll";
    int numEvents = ::poll(_pollfds.data(), _pollfds.size(), timeoutMs);
    LOG_TRACE << "after sys poll";
    Timestamp now(Timestamp::now());
    if (numEvents > 0) {
        LOG_TRACE << numEvents << " events happened";
        fillActiveChannels(numEvents, activeChannels);
    } else if (numEvents == 0) {
        LOG_TRACE << " nothing happended";
    } else {
        LOG_SYSERR << "Poller::poll()";
    }

    return now;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值