通过 Socket 通过 boost asio 发送和接收 protobuf 数据

Sending and receiving protobuf data over Socket via boost asio

本文关键字:通过 protobuf 数据 Socket boost asio      更新时间:2023-10-16

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

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

所以我尝试序列化我的数据并使用 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 倍的发送函数(我猜我的数据接缝要发送),但我的客户端接缝永远不会获取数据......

你的客户端挂在这条线上

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 - 请参阅参考。

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。

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。

如果您知道readwithtransfer_all在发生错误时结束,则可以创建此错误以查看读取的数据。您可以在服务器端关闭套接字(用于发送操作)或仅关闭此套接字。然后,您可以更改read调用以获取error_code,您应该看到文件结尾为错误:

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 个字节上),然后在此标头之后稍后发送对象的内容。

在客户端:

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));