使用boost :: asio从套接字读取JSON

hfh*_*hc2 4 c++ sockets json boost-asio

我目前正在尝试使用boost-asio的套接字API通过网络将一些JSON数据从客户端传输到服务器.我的客户基本上这样做:

int from = 1, to = 2;

boost::asio::streambuf buf;
ostream str(&buf);

str << "{"
    << "\"purpose\" : \"request\"" << "," << endl
    << "\"from\" : " << from << "," << endl
    << "\"to\" : " << to << "," << endl
    << "}" << endl;

// Start an asynchronous operation to send the message.
boost::asio::async_write(socket_, buf,
    boost::bind(&client::handle_write, this, _1));
Run Code Online (Sandbox Code Playgroud)

在服务器端,我可以选择各种boost::asio::async_read*功能.我想使用JsonCpp来解析收到的数据.研究JsonCpp API(http://jsoncpp.sourceforge.net/class_json_1_1_reader.html)我发现Reader在std::stringa*,char*数组或者std::istream我可以从boost::asio::streambuf传递给函数的操作中运行.

关键是,据我所知,不一定是整个内容一次传输的情况,所以我需要某种确认缓冲区包含足够的数据来使用JsonCpp处理整个文档.如何确保缓冲区包含足够的数据?

seh*_*ehe 7

这是应用程序级协议的一个区域

  • 读取直到流结束(发送方断开连接); 这不适用于为多个消息保持活动状态的连接
  • 提供一个标题Content-Length: 12346\r\n,以提前知道要读多少
  • 提供分隔符(有点像mime边界,但您可以使用任何不允许/不支持的序列作为JSON有效负载的一部分)(async_read_until)
  • 将有效载荷视为"二进制样式"(例如BSON)并在文本传输之前提供(网络顺序)长度字段.

ASIO Http服务器示例包含一个非常好的模式,用于解析您可以使用的HTTP请求/标头.这假设您的解析器可以检测完整性,并且只有"软失败"才会出现所有信息.

void connection::handle_read(const boost::system::error_code& e,
    std::size_t bytes_transferred)
{
  if (!e)
  {
    boost::tribool result;
    boost::tie(result, boost::tuples::ignore) = request_parser_.parse(
        request_, buffer_.data(), buffer_.data() + bytes_transferred);

    if (result)
    {
      request_handler_.handle_request(request_, reply_);
      boost::asio::async_write(socket_, reply_.to_buffers(),
          boost::bind(&connection::handle_write, shared_from_this(),
            boost::asio::placeholders::error));
    }
    else if (!result)
    {
      reply_ = reply::stock_reply(reply::bad_request);
      boost::asio::async_write(socket_, reply_.to_buffers(),
          boost::bind(&connection::handle_write, shared_from_this(),
            boost::asio::placeholders::error));
    }
    else
    {
      socket_.async_read_some(boost::asio::buffer(buffer_),
          boost::bind(&connection::handle_read, shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }
  }
  else if (e != boost::asio::error::operation_aborted)
  {
    connection_manager_.stop(shared_from_this());
  }
}
Run Code Online (Sandbox Code Playgroud)

我提供了一个使用Boost Spirit解析JSON的答案,之后使用QJsonDocument将子字符串解析为JSON ; 您可以使用它来检测正确的JSON文档的结尾(如果它不完整,结束将与开始一致)