Boost Asio async_send 产生哔声

Posted

技术标签:

【中文标题】Boost Asio async_send 产生哔声【英文标题】:Boost Asio async_send produces beep sound 【发布时间】:2016-07-27 17:21:19 【问题描述】:

尝试为一种行为类似于回显服务器的服务器编写客户端。当我尝试发送某些东西时,它会发出哔声。我发现问题出现在 win_iocp_socket_service_base.ipp 文件的第 356 行(在我的编辑器上)。代码是:

int result = ::WSASend(impl.socket_, buffers,
        static_cast<DWORD>(buffer_count), &bytes_transferred, flags, op, 0);

然后我做了一些研究。

Continuous boost::asio reads这里在答案的评论中,有人说当二进制数据被写入std::cout时。

Why does the following code make my computer beep? 这里,看来问题是一样的。他们得出的结论是“\a”是产生声音的原因。

调试应用,我前面提到的API函数的缓冲区,包含以下内容:

"asd@ıııı2•Z\x1aP"

这里“asd@”是我的字符串,其余的每次调试时都会改变,我不知道它们是什么。现在,这可能是产生声音的部分,但我的问题是如何防止它?

我有以下一轮“对应”功能的实现。请注意,我还有一个独立的Send() 函数实现,可以显式与ReadUntil() 配对以达到相同的结果。将Send()ReadUntil() 一起使用,仍然会产生哔声。通常,这不应该发生,因为我不是处理低级 API 函数,而是 Boost.Asio。我做错了吗?

代码

void Correspond(const std::string &data,
                const std::string &delim,
                std::vector<char> &response)

    std::shared_ptr<std::vector<char>> localbuffer = std::make_shared<std::vector<char>>(data.begin(), data.end());

    // pass shared_ptr to callback function to prolong the buffer's lifetime
    // !!! perhaps a better buffer management is needed
    socket.async_send(boost::asio::buffer(*localbuffer),
                      std::bind(&TCPClient::on_correspond,
                                this,
                                std::placeholders::_1,
                                std::placeholders::_2,
                                delim,
                                std::ref(response),
                                localbuffer));

及后续回调实现

void on_correspond(const boost::system::error_code& errorcode,
                   std::size_t sent,
                   const std::string &delim,
                   std::vector<char> &response,
                   const std::shared_ptr<std::vector<char>> &buffer)

    if(errorcode) 
        SLOGERROR(mutex, errorcode.message(), "on_correspond()");
    

    if(sent == 0) 
        SLOG(mutex, "0 bytes sent w/o errors", "on_correspond()");
    

    ReadUntil(delim, response);

深入API调试后,发现这个问题与读取功能无关,但我会在这里发布以确保。

void ReadUntil(const std::string &delim, std::vector<char> &response)

    boost::asio::async_read_until(socket,
                                  buffer,
                                  delim,
                                  std::bind(&TCPClient::on_readuntil,
                                            this,
                                            std::placeholders::_1,
                                            std::placeholders::_2,
                                            std::ref(response)));

void on_readuntil(const boost::system::error_code& errorcode,
                  std::size_t received,
                  std::vector<char> &response)

    SLOG(mutex, "on_readuntil invoked", "on_readuntil()");
    SLOG(mutex, received, "on_readuntil");
    // !!! needs error handling, short-read handling and whatnot
    if(errorcode) 
        SLOGERROR(mutex, errorcode.message(), "on_readuntil()");
        return;
    

    if(received == 0) 
        SLOG(mutex, "0 bytes received w/o errors", "on_readuntil()");
    

    response.reserve(received);
    std::copy(boost::asio::buffers_begin(buffer.data()),
              boost::asio::buffers_begin(buffer.data()) + received,
              std::back_inserter(response));
    buffer.consume(received);

【问题讨论】:

here "asd@" is my string, the rest changes every time when I debug 看起来像读取缓冲区而不关心它的大小,欢迎使用 C++。可能想给 boost::asio::buffer 一个关于缓冲区大小的提示。 你的意思是我应该准备()缓冲区?我本来打算手动管理所有的提交和消费,但是here,有人告诉我如果boost::asio::streambuf本身用于asio函数,它是自动管理的。 您是否尝试过禁用控制台输出并进行测试以查看是否仍然收到哔哔声? @Xirema,禁用各种控制台日志/输出没有帮助 @Backtempel,我想我误解了你想说的。我以为您在谈论读取功能,而实际上问题(可能)与发送功能有关。在将数据大小提供给 Send()Correspond() 函数中使用的 boost::asio::buffer 之后,它停止了哔哔声(最终)。如果你写一个答案,我会接受它。我不敢相信我错过了:> 【参考方案1】:

here "asd@" is my string, the rest changes every time when I debug

缓冲区被读取而不关心它的大小,欢迎使用 C++。给 boost::asio::buffer 缓冲区大小。

【讨论】:

问题又出现了,很遗憾。经过进一步调试,我意识到 shared_ptr 的内容和我试图发送的消息是相同的。喜欢关注[Raw View] _Myval2=_Myfirst=0x004828a8 "asd@ııııú¥¿\x2" _Mylast=0x004828ac "ııııú¥¿\x2" _Myend=0x004828ac "ııııú¥¿\x2" std::_Compressed_pair&lt;std::_Wrap_alloc&lt;std::allocator&lt;char&gt; &gt;,std::_Vector_val&lt;std::_Simple_types&lt;char&gt; &gt;,1&gt;。注意 asd@ııııú¥¿\x2,这是 WSASend() 尝试发送并引起哔声的确切字符串。您认为问题出在哪里? @CengizKandemir 你能发一个MCVE 来重现你的问题吗?我正在打电话,我稍后再看问题。 我无法正确重现该问题。我试过的 MCVE 没有发出哔哔声。我还重新编译了我正在使用的回显服务器示例,也许它实际上是由于服务器端的一些有问题的 cout 而发出哔哔声的服务器。如果我进一步隔离问题,我会在这里写。

以上是关于Boost Asio async_send 产生哔声的主要内容,如果未能解决你的问题,请参考以下文章

async_send 数据未发送

boost::asio::streambuf 基本用法和注意事项

使用 boost::asio::async_wait_until 和 boost::asio::streambuf

boost asio 学习 boost::asio 网络封装

Boost::Asio入门剖析

websocketpp 和 boost.asio 有啥区别?