C++ boost::asio::async\u write使用\0开始的字符串到达另一端

C++ boost::asio::async\u write使用\0开始的字符串到达另一端,c++,boost,boost-asio,C++,Boost,Boost Asio,我不是boost专家,我正在尝试使用boost::asio。一切都很好,直到我把事情搞砸了。不幸的是,我不知道我做了什么=P 下面是发生的情况: 我有一个服务器,它是一个C++ Builder应用程序,它打开了一个我的客户机应用程序(VisualStudioC++ + DLL)连接的套接字。 当我尝试向套接字写入内容时,没有收到任何错误,但服务器收到如下字符串:“\0SomeText”。我不知道这\0是从哪里来的 下面是一些可能会澄清问题的代码: void CometClient::Se

我不是boost专家,我正在尝试使用boost::asio。一切都很好,直到我把事情搞砸了。不幸的是,我不知道我做了什么=P

下面是发生的情况:

我有一个服务器,它是一个C++ Builder应用程序,它打开了一个我的客户机应用程序(VisualStudioC++ + 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
    }
}
void CometClient::SendCommand()
{
if(套接字打开()
{
TCommands::iterator it=pending_命令。begin();
while(it!=pending_commands.end())
{
std::向量vctCommand;
分配((*it.begin(),(*it.end());
vctCommand.push_back('\n');
boost::shared_ptr ptr_command=boost::make_shared(vctCommand);
boost::asio::async_写入(socket_,boost::asio::buffer(*ptr_命令),
boost::bind(&CometClient::handle_write_请求,
boost::asio::占位符::错误,ptr_命令)
);
it=挂起的_命令。擦除(it);
}
}
其他的
{
//某物
}
}
void CometClient::handle_write_请求(const boost::system::error_code&err,boost::shared_ptr命令)
{
如果(!err)
{
std::vector*ptr=command.get();
boost::asio::异步\u读取\u直到(套接字\u,响应\u,“\n”,
boost::bind(&CometClient::handle_read_内容,
boost::asio::占位符::错误);
}
其他的
{
//某物
}
}
任何帮助都将不胜感激

提前谢谢

编辑:

以下是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
    }
}
void CometClient::SendCommand()
{
//bConnected告诉我服务器是否已经应答,而Connected只告诉我套接字是否打开(将在不久的将来更改)
if(已连接()&&pending_命令.size()&&b已连接)
{
std::向量vctCommand;
std::string sCommand(挂起的命令.front().c_str());
挂起的_命令。pop_front();
vctCommand.assign(sCommand.begin(),sCommand.end());
vctCommand.push_back('\n');
boost::shared_ptr ptr_command=boost::make_shared(vctCommand);
boost::asio::async_write(socket),boost::asio::buffer(*ptr_命令,sCommand.length()),
boost::bind(&CometClient::handle_write_请求,
boost::asio::占位符::错误,ptr_命令)
);
}
其他的
{
//某物
}
}
void CometClient::handle_write_请求(const boost::system::error_code&err,boost::shared_ptr命令)
{
如果(!err)
{
std::vector*ptr=command.get();
boost::asio::异步\u读取\u直到(套接字\u,响应\u,“\n”,
boost::bind(&CometClient::handle_read_内容,
boost::asio::占位符::错误);
SendCommand();
}
其他的
{
//某物
}
}

您正在生成对
async\u write()
的多个并发调用。这些调用不保证是原子的或按顺序的。原因是
async\u write()
是通过对
async\u write\u some()
的多次调用来实现的,调用者必须确保与任何一次一样,只有一个
async\u write()
正在进行中

更好的方法是将第一个命令从队列中出列,并在完成处理程序中启动下一次写入。这可能是一个你意想不到的伪字节的原因


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

我将此项保留在此处以供记录

其中一个问题正是janm所说的,事实上我正在对async_write进行多个并发调用。我已经解决了这个问题,但这还不够。与一位朋友交谈时,我们发现我发送的字符串大小错误,因此我对代码做了一些更改,下面我将粘贴最后一个aproach,这很有效。=)

我学到的是:

  • 小心不要对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
    }
}

你是对的,我对async_write()进行了多次并发调用。不幸的是,修复该问题并没有解决问题。。。我m仍然在请求字符串中发送\0。。。。还有其他想法吗?我的向量包含正确的数据。。。