boost :: asio :: async_write以\ 0开始字符串到达​​另一端

时间:2013-07-03 22:15:53

标签: c++ boost boost-asio

我不是助推器专家,我正在尝试使用boost :: asio。一切顺利,直到我把事情搞砸了。不幸的是我不知道我做了什么...... = P

以下是发生的事情:

我有一个服务器,它是一个C ++ Builder应用程序,用于打开我的客户端应用程序(Visual Studio C ++ DLL)连接的套接字。

当我尝试向套接字写入内容时,我没有收到任何错误,但服务器收到如下字符串:“\ 0SomeText”。我不知道\ 0来自哪里。

下面的一些代码可能会让事情变得清晰:

    void CometClient::SendCommand()
{
    if (socket_.is_open())
    {
        TCommands::iterator it = pending_commands.begin();
        while (it != pending_commands.end())
        {
            std::vector<char> vctCommand;
            vctCommand.assign((*it).begin(), (*it).end());
            vctCommand.push_back('\n');
            boost::shared_ptr<std::vector<char> > ptr_command = boost::make_shared<std::vector<char> > (vctCommand);

            boost::asio::async_write(socket_, boost::asio::buffer( *ptr_command ) ,
                boost::bind(&CometClient::handle_write_request, this,
                    boost::asio::placeholders::error, ptr_command )
                );
            it = pending_commands.erase(it);
        }

    }
    else
    {
        // Something
    }
}

void CometClient::handle_write_request(const boost::system::error_code& err, boost::shared_ptr< std::vector<char> > command)
{
    if (!err)
    {
        std::vector<char> * ptr = command.get();
        boost::asio::async_read_until(socket_, response_, "\n",
            boost::bind(&CometClient::handle_read_content, this,
            boost::asio::placeholders::error));
    }
    else
    {
        // Something
    }
}

非常感谢任何帮助。

提前致谢!

编辑:

这是我在janm回答后所拥有的:

    void CometClient::SendCommand()
{
    // bConnected tells me if the server has already answered me and Connected just tells me if the socket is open (will change in the near future)
    if (Connected() && pending_commands.size() && bConnected)
    {
        std::vector<char> vctCommand;
        std::string sCommand(pending_commands.front().c_str());
        pending_commands.pop_front();
        vctCommand.assign(sCommand.begin(), sCommand.end());
        vctCommand.push_back('\n');
        boost::shared_ptr<std::vector<char> > ptr_command = boost::make_shared<std::vector<char> > (vctCommand);

        boost::asio::async_write(socket_, boost::asio::buffer( *ptr_command, sCommand.length() ) ,
            boost::bind(&CometClient::handle_write_request, this,
            boost::asio::placeholders::error, ptr_command )
            );
    }
    else
    {
        // Something
    }
}

void CometClient::handle_write_request(const boost::system::error_code& err, boost::shared_ptr< std::vector<char> > command)
{
    if (!err)
    {
        std::vector<char> * ptr = command.get();
        boost::asio::async_read_until(socket_, response_, "\n",
            boost::bind(&CometClient::handle_read_content, this,
            boost::asio::placeholders::error));
        SendCommand();
    }
    else
    {
        // Something
    }
}

2 个答案:

答案 0 :(得分:2)

您正在为async_write()生成多个并发呼叫。这些调用不保证是原子的或按顺序的。原因是async_write()是根据对async_write_some()的多次调用实现的,调用方必须确保一次只有一个async_write()正在进行中。

更好的方法是将第一个命令从队列中出列,然后在完成处理程序中启动下一个写入。这可能是你不期望的虚假字节的原因。

要检查的另一件事是你的矢量确实包含你认为它们包含的内容。使用调试器或发出的日志输出进行检查。

答案 1 :(得分:0)

我会留在这里仅供记录。

其中一个问题正是janm所说的,实际上我正在对async_write进行多次并发调用。我ve fixed that and it wasn足够了。和朋友说话,我们发现我的字符串发送的大小错误,所以我已经改变了一些代码,而且我已经粘贴了最终的方法,这是有效的。 =)

我学到了什么:

  • 小心不要对async_write进行多次并发调用
  • 注意以便发送正确的字节数
  • 请记住,在async_write调用结束之前,请保持缓冲区内容处于活动状态

非常感谢@janm

void CometClient::AddCommand(std::string _command)
{
    pending_commands.push_back(_command);
    ExecuteCommands();
}

void CometClient::ExecuteCommands()
{
    if (Conectado() && pending_commands.size())
    {
        boost::asio::async_write(socket_, boost::asio::buffer( pending_commands.front(), pending_commands.front().length() ) ,
            boost::bind(&CometClient::handle_write_request, this,
            boost::asio::placeholders::error)
            );
    }
    else
    {
        // Something
    }
}

void CometClient::handle_write_request(const boost::system::error_code& err)
{
    if (!err)
    {
        pending_commands.pop_front();
        boost::asio::async_read_until(socket_, response_, "\n",
            boost::bind(&CometClient::handle_read_content, this,
            boost::asio::placeholders::error));
        ExecuteCommands();
    }
    else
    {
        // Something
    }
}