如何使用 boost::asio::async_read_until 并将外部内存地址作为缓冲区

发布于 2024-12-08 14:07:22 字数 181 浏览 2 评论 0原文

async_read_until 需要一个 basic_streambuf 来读取数据。我不想分配额外的内存,而是使用内存地址(来自不允许更改的指定接口)作为目标缓冲区。

是否可以使用外部内存地址创建一个streambuf,或者我是否需要编写一个包装类?

async_read_until expects a basic_streambuf into which the data will be read. I don't want to allocate additional memory, but using a memory address (from a specified interface that I'm not allowed to change) as the target buffer.

Is it possible to create a streambuf with an external memory address or do I need to write a wrapper-class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痕至 2024-12-15 14:07:22

最后通过编写我自己的 async_read_until_delim 类解决了这个问题,该类需要内存指针和要读取的最大字节值。它尽可能接近原始的 boost 实现,但进行了一些调整,这应该会带来更高的执行性能。

namespace {

template<typename read_handler>
class async_read_until_delim
{
public:
    async_read_until_delim(tcp::socket& socket, void* buffer, std::size_t max_read_size_in_bytes,
        char delim, read_handler& handler)
            : m_socket(socket), m_cur(static_cast<char*>(buffer)),
              m_end(static_cast<char*>(buffer) + max_read_size_in_bytes), m_delim(delim),
              m_handler(handler), m_pos(0)
        {
            read_some();
        }
    async_read_until_delim(async_read_until_delim const& other)
        : m_socket(other.m_socket), m_cur(other.m_cur), m_end(other.m_end), m_delim(other.m_delim),
          m_handler(other.m_handler), m_pos(other.m_pos)
        {
        }

    void operator()(boost::system::error_code const& error, std::size_t bytes_transferred)
        {
            if (!error)
            {    
                if (std::find(m_cur, m_end, m_delim) != m_end)
                {
                    m_handler(error, m_pos + bytes_transferred);
                    return;
                }
                else if (m_cur == m_end)
                {
                    m_handler(boost::asio::error::not_found, -1);
                    return;
                }

                m_cur += bytes_transferred;
                m_pos += bytes_transferred;

                read_some();
            }
            else
                m_handler(error, m_pos);
        }

private:
    void read_some()
        {
            m_socket.async_read_some(
                boost::asio::buffer(m_cur, m_end - m_cur), async_read_until_delim(*this));
        }

    tcp::socket&  m_socket;
    char         *m_cur,
                 *m_end;
    char          m_delim;
    read_handler  m_handler;
    std::size_t   m_pos;
};

template<typename read_handler>
inline void do_async_read_until_delim(tcp::socket& socket, void* buffer, std::size_t max_read_size_in_bytes,
    char delim, read_handler& handler)
{
    async_read_until_delim<read_handler>(socket, buffer, max_read_size_in_bytes, delim, handler);
}

} /* anonymous namespace */

所以,我希望它对某人也有用。

Finally solved the issue by writing my own async_read_until_delim class which expects a memory-pointer and a maximum value of bytes to read. It's as close as possible to the original boost implementation, but has a few adjustments which should lead to a more performant execution.

namespace {

template<typename read_handler>
class async_read_until_delim
{
public:
    async_read_until_delim(tcp::socket& socket, void* buffer, std::size_t max_read_size_in_bytes,
        char delim, read_handler& handler)
            : m_socket(socket), m_cur(static_cast<char*>(buffer)),
              m_end(static_cast<char*>(buffer) + max_read_size_in_bytes), m_delim(delim),
              m_handler(handler), m_pos(0)
        {
            read_some();
        }
    async_read_until_delim(async_read_until_delim const& other)
        : m_socket(other.m_socket), m_cur(other.m_cur), m_end(other.m_end), m_delim(other.m_delim),
          m_handler(other.m_handler), m_pos(other.m_pos)
        {
        }

    void operator()(boost::system::error_code const& error, std::size_t bytes_transferred)
        {
            if (!error)
            {    
                if (std::find(m_cur, m_end, m_delim) != m_end)
                {
                    m_handler(error, m_pos + bytes_transferred);
                    return;
                }
                else if (m_cur == m_end)
                {
                    m_handler(boost::asio::error::not_found, -1);
                    return;
                }

                m_cur += bytes_transferred;
                m_pos += bytes_transferred;

                read_some();
            }
            else
                m_handler(error, m_pos);
        }

private:
    void read_some()
        {
            m_socket.async_read_some(
                boost::asio::buffer(m_cur, m_end - m_cur), async_read_until_delim(*this));
        }

    tcp::socket&  m_socket;
    char         *m_cur,
                 *m_end;
    char          m_delim;
    read_handler  m_handler;
    std::size_t   m_pos;
};

template<typename read_handler>
inline void do_async_read_until_delim(tcp::socket& socket, void* buffer, std::size_t max_read_size_in_bytes,
    char delim, read_handler& handler)
{
    async_read_until_delim<read_handler>(socket, buffer, max_read_size_in_bytes, delim, handler);
}

} /* anonymous namespace */

So, I hope it will be usefull for someone too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文