boost::asio::async_write使用0开头的字符串到达另一端
boost::asio::async_write gets to the other side with a started string
我不是boost专家,我正在尝试使用boost::asio。一切都很好,直到我把事情搞砸了。不幸的是,我不确定我做了什么=P
情况如下:
我有一个服务器,它是一个C++Builder应用程序,它打开了一个套接字,我的客户端应用程序(Visual Studio C++DLL)连接到该套接字。
当我尝试向套接字写入内容时,我没有收到任何错误,但服务器收到的字符串如下:"\0SomeText"。我不知道那是从哪里来的。
下面是一些可能会澄清问题的代码:
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
}
}
您正在生成对async_write()
的多个并发调用。这些调用不能保证是原子调用或按顺序调用。原因是async_write()
是根据对async_write_some()
的多次调用来实现的,调用者必须确保在任何一次都只有一个async_write()
在进行中。
更好的方法是将队列中的第一个命令出列,然后在完成处理程序中启动下一个写入。这可能是你意想不到的虚假字节的原因。
另一件需要检查的事情是,你的向量是否真的包含了你认为它们包含的内容。使用调试器或发出的日志输出对此进行检查。
我将把它留在这里作为记录。
其中一个问题正是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
}
}