提升 asio TCP + google proto
Boost asio TCP + google proto
我的第一步是使用 boost asio 和 google proto。我定义了一个小测试消息
message Test
{
optional string test=1;
optional int32 value=2;
}
和一个异步增强 asio 服务器,它响应以下函数:
void start()
{
Test test;
test.set_test("test");
test.set_value(44444);
test.PrintDebugString();
boost::asio::async_write(socket_, boost::asio::buffer(test.SerializeAsString()),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
我的测试客户是
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include "test.pb.h"
using boost::asio::ip::tcp;
int main(int argc, char* argv[])
{
try
{
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::endpoint end_point(boost::asio::ip::address::from_string("127.0.0.1"), 15000);
tcp::socket socket(io_service);
socket.connect(end_point);
std::string data;
for (;;)
{
boost::array<char, 128> buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
if (error == boost::asio::error::eof)
{
Test test;
test.ParseFromString(data);
test.PrintDebugString();
break; // Connection closed cleanly by peer.
}
else if (error)
throw boost::system::system_error(error); // Some other error.
data.append(buf.begin(), buf.end());
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
如果我用我的客户端多次调用我的服务器,我会得到不同的输出:
test: "test"
value: 44444
533 {
}
test: "test"
value: 44444
1644{
}
test: "test"
value: 44444
最后的输出符合预期,其余的都是错误的。我不明白为什么我得到的输出比我服务器上的输出大:
test: "test"
value: 44444
有人知道为什么我会得到类似“1644{ }”的信息吗?
我认为我的eof是错误的还是?
编辑
message Header
{
required int32 size=1;
}
新的开始
void start()
{
boost::asio::async_read(socket_,
boost::asio::buffer(m_headerData, m_sizeOfHeader),
boost::bind(&tcp_connection::handle_read_header, this,
boost::asio::placeholders::error));
}
成员:
const size_t m_sizeOfHeader = sizeof(Header::default_instance().SerializeAsString());
boost::array<char, sizeof(Header::default_instance().SerializeAsString())> m_headerData;
void handle_read_header(const boost::system::error_code& error_code)
{
if (!error_code)
{
Header header;
header.ParseFromString(std::string(m_headerData.begin(), m_headerData.end()));
header.PrintDebugString();
}
else
{
std::cout << error_code.message()<< "ERROR DELETE READ \n";
delete this;
}
我现在用这种方式尝试了 header,但出现以下错误:
操作已取消或文件描述符错误
我的新客户发送:
Header header;
header.set_size(101);
boost::asio::write(socket,boost::asio::buffer(header.SerializeAsString())) ;
我认为问题是变量 m_sizeOfHeader 是错误的...在我的服务器端我得到 8,当我在客户端打印 write 的输出时我得到 2...
我不明白为什么 header 的尺码不固定...我只有一个必填字段
您忽略了读取的字节数 (len
) 并将垃圾附加到 data
中:
data.append(buf.begin(), buf.end());
试试看:
data.append(buf.begin(), buf.begin() + len);
此外,您的代码只有在发送单个消息并且之后立即正常关闭套接字(使用 shutdown
)时才能正常工作。在更复杂的情况下,您将需要某种允许确定消息边界的协议。例如,您可以在消息前的前两个字节发送消息大小,在接收方首先读取具有预期消息大小的两个字节,然后读取消息正文。
我的第一步是使用 boost asio 和 google proto。我定义了一个小测试消息
message Test
{
optional string test=1;
optional int32 value=2;
}
和一个异步增强 asio 服务器,它响应以下函数:
void start()
{
Test test;
test.set_test("test");
test.set_value(44444);
test.PrintDebugString();
boost::asio::async_write(socket_, boost::asio::buffer(test.SerializeAsString()),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
我的测试客户是
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include "test.pb.h"
using boost::asio::ip::tcp;
int main(int argc, char* argv[])
{
try
{
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::endpoint end_point(boost::asio::ip::address::from_string("127.0.0.1"), 15000);
tcp::socket socket(io_service);
socket.connect(end_point);
std::string data;
for (;;)
{
boost::array<char, 128> buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
if (error == boost::asio::error::eof)
{
Test test;
test.ParseFromString(data);
test.PrintDebugString();
break; // Connection closed cleanly by peer.
}
else if (error)
throw boost::system::system_error(error); // Some other error.
data.append(buf.begin(), buf.end());
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
如果我用我的客户端多次调用我的服务器,我会得到不同的输出:
test: "test"
value: 44444
533 {
}
test: "test"
value: 44444
1644{
}
test: "test"
value: 44444
最后的输出符合预期,其余的都是错误的。我不明白为什么我得到的输出比我服务器上的输出大:
test: "test"
value: 44444
有人知道为什么我会得到类似“1644{ }”的信息吗?
我认为我的eof是错误的还是?
编辑
message Header
{
required int32 size=1;
}
新的开始
void start()
{
boost::asio::async_read(socket_,
boost::asio::buffer(m_headerData, m_sizeOfHeader),
boost::bind(&tcp_connection::handle_read_header, this,
boost::asio::placeholders::error));
}
成员:
const size_t m_sizeOfHeader = sizeof(Header::default_instance().SerializeAsString());
boost::array<char, sizeof(Header::default_instance().SerializeAsString())> m_headerData;
void handle_read_header(const boost::system::error_code& error_code)
{
if (!error_code)
{
Header header;
header.ParseFromString(std::string(m_headerData.begin(), m_headerData.end()));
header.PrintDebugString();
}
else
{
std::cout << error_code.message()<< "ERROR DELETE READ \n";
delete this;
}
我现在用这种方式尝试了 header,但出现以下错误:
操作已取消或文件描述符错误
我的新客户发送:
Header header;
header.set_size(101);
boost::asio::write(socket,boost::asio::buffer(header.SerializeAsString())) ;
我认为问题是变量 m_sizeOfHeader 是错误的...在我的服务器端我得到 8,当我在客户端打印 write 的输出时我得到 2...
我不明白为什么 header 的尺码不固定...我只有一个必填字段
您忽略了读取的字节数 (len
) 并将垃圾附加到 data
中:
data.append(buf.begin(), buf.end());
试试看:
data.append(buf.begin(), buf.begin() + len);
此外,您的代码只有在发送单个消息并且之后立即正常关闭套接字(使用 shutdown
)时才能正常工作。在更复杂的情况下,您将需要某种允许确定消息边界的协议。例如,您可以在消息前的前两个字节发送消息大小,在接收方首先读取具有预期消息大小的两个字节,然后读取消息正文。