通过 boost asio 通过 Socket 发送和接收 protobuf 数据 [英] Sending and receiving protobuf data over Socket via boost asio

查看:137
本文介绍了通过 boost asio 通过 Socket 发送和接收 protobuf 数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过 TCP 套接字将 Protobuf 数据从我的服务器发送到我的客户端.

I want to send Protobuf data from my server to my client thanks to a TCP socket.

我测试了我的客户端和服务器,并且 TCP 连接正常工作.

I tested my client and my server and the TCP connexion works.

所以我尝试序列化我的数据并使用流缓冲发送它.

So I try to serialize my data and send it by using a streambuf.

在我的服务器中:

void SendData(protobufType data){
        std::ostream ostream(&this->m_streambuf);
        data.SerializeToOstream(&ostream);

        std::cout<<"Send data"<< std::endl;
        boost::asio::write(this->m_socket, this->m_streambuf);
}

在我的客户端:

boost::asio::streambuf response;
boost::asio::read(socket, response);
std::cout<<"Data received"<< std::endl;

我运行了 3 次我的发送函数(我猜我的数据接缝要发送)但我的客户端接缝永远无法获取数据......

I run 3 times my send function (I guess my data seams to be sent) but myclient seams to never get data ...

推荐答案

你的客户挂在这条线上

boost::asio::read(socket, response);

因为上面和

boost::asio::read(socket, response, boost::asio::tranfer_all());

中描述的内容文档.

您使用需要完成条件的 read 重载.这些函子分为三种:transfer_all_ttransfer_exactly_ttransfer_at_least_t.他们每个人都有 operator()() 如果读取操作完成则返回 0 - 参见参考.

You use read overload which takes completion condition. There are three kinds of these functors: transfer_all_t, transfer_exactly_t and transfer_at_least_t. Each of them has operator()() which returns 0 if read operation is completion - see reference.

transfer_all_t::opeator()() 的代码是:

  template <typename Error>
  std::size_t operator()(const Error& err, std::size_t)
  {
    return !!err ? 0 : default_max_transfer_size;
  }

所以只有在发生错误时才返回 0.

so 0 is returned only if an error occurres.

transfer_at_least_t::operator()() 是:

  template <typename Error>
  std::size_t operator()(const Error& err, std::size_t bytes_transferred)
  {
    return (!!err || bytes_transferred >= minimum_)
      ? 0 : default_max_transfer_size;
  }

如您所见,如果发生错误或至少传输了 minimum_ 字节,则返回 0.

as you can see 0 is returned if either an error occurred or at least minimum_ bytes were transferred.

如果您知道 readtransfer_all 在发生错误时结束,您可以创建这个错误来查看读取的数据.您可以在服务器端关闭套接字(用于发送操作)或关闭此套接字.然后您可以更改 read 调用以获取 error_code 并且您应该看到 End of file 为错误:

If you know that read with transfer_all ends when an error occurres, you can create this error to see read data. You can shutdown socket (for sending operation) on the server side or just close this socket. Then you can change read call to get error_code and you should see End of file as error:

boost::system::error_code ec;
boost::asio::read(socket,response,ec);
if (ec)
{
   cout << ec.message() << endl; // End of file
   // if ec is End of file you can see what data was read into streambuf
}

<小时>

您发送一个序列化对象,因此您知道该对象的大小,为什么不使用发送对象大小的方法(例如,4 个字节),然后在此标头之后发送对象的内容.


You send a serialized object, so you know the size of this object, why not use the approach where you are sending the size of object (for example on 4 bytes) then after this header the content of object is sent later.

在客户端:

array<char,4> length;
boost::asio::read(socket,boost::asio::buffer(length));
int contentLen = /*conversion from length array into integer */
vector<char> content( contentLen );
boost::asio::read(socket,boost::asio::buffer(content));

这篇关于通过 boost asio 通过 Socket 发送和接收 protobuf 数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆