问题描述
我正在使用FlatBuffers和Boost ASIO
这是我形成消息并将其从客户端发送到服务器的方式:
size_t const header_length = 8;
size_t const body_size_b = 8;
std::string data;
ServerOpcode opc;
opc = ServerOpcode::SMSG_LOGIN_REQUEST_RESPONSE_TEST;
flatbuffers::FlatBufferBuilder builder;
auto name = builder.CreateString("Orc Monster");
auto accountRole = Vibranium::CreateAccountRole_Packet(builder,1,name);
std::ostringstream header_stream;
header_stream << std::setw(header_length) << std::hex << opc;
std::ostringstream body_size_stream;
body_size_stream << std::setw(body_size_b) << std::hex << builder.GetSize();
data += header_stream.str();
data += body_size_stream.str();
boost::asio::streambuf b;
std::ostream os(&b);
size_t request_length = data.length();
boost::asio::write(s,boost::asio::buffer(data,request_length));
boost::asio::write(s,boost::asio::buffer(&accountRole,builder.GetSize()));
这是我在服务器端阅读的方式:
void Vibranium::Client::read_header() {
auto self(shared_from_this());
_packet.header_.resize(Packet::header_size_in_bytes);
boost::asio::async_read(socket,boost::asio::buffer(_packet.header_,Packet::header_size_in_bytes),[this,self](boost::system::error_code ec,std::size_t /*length*/)
{
if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec))
{
disconnect();
}
else
{
std::ostringstream header_stream;
header_stream << std::setw(Packet::header_size_in_bytes) << std::hex << _packet.header_;
std::cout << "Header: " << std::endl;
std::cout << std::hex << header_stream.str() << std::endl;
read_body_size();
}
});
}
void Vibranium::Client::read_body_size() {
auto self(shared_from_this());
_packet.body_size_.resize(Packet::body_size_in_bytes);
socket.async_read_some(boost::asio::buffer(_packet.body_size_,Packet::body_size_in_bytes),std::size_t length)
{
if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec))
{
disconnect();
}
else
{
std::cout << "Body Size: " << std::endl;
std::cout << _packet.body_size_ << std::endl;
std::stringstream ss;
ss << std::hex << _packet.body_size_;
ss >> _packet.body_in_bytes;
read_body();
}
});
}
void Vibranium::Client::read_body() {
auto self(shared_from_this());
_packet.body_.resize(_packet.body_in_bytes);
socket.async_read_some(boost::asio::buffer(_packet.body_,_packet.body_in_bytes),std::size_t length)
{
if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec))
{
disconnect();
}
else
{
try
{
auto ac = GetAccountRole_Packet(&_packet.body_);
std::cout << ac->name()->str() << std::endl;
}
catch (std::exception& e)
{
std::cout << "Error bace!" << std::endl;
// Unable to decode data.
boost::system::error_code error(boost::asio::error::invalid_argument);
return;
}
std::cout << "Body: " << std::endl;
std::cout << _packet.body_ << std::endl;
//Send(ServerOpcode::SMSG_AUTH_CONNECTION_RESPONSE,"How are you,mate?");
read_header();
}
});
}
void Vibranium::Client::disconnect() const {
Logger::Log("disconnected ID: " + std::__cxx11::to_string(this->connectionId),Logger::Error,true);
for (int i = 0; i < Vibranium::Server::Clients.size(); ++i) {
if(Vibranium::Server::Clients[i]->connectionId == this->connectionId)
Vibranium::Server::Clients.erase(Vibranium::Server::Clients.begin() + i);
}
}
在服务器端收到消息时,我得到以下输出:
Header:
a99
Body Size:
24
Segmentation fault (core dumped)
然后,如果我尝试查看有关gdb seg错误的更多详细信息,则会看到以下输出:
Core was generated by `./AuthServer'.
Program terminated with signal SIGSEGV,Segmentation fault.
#0 0x00007f0ad833c202 in flatbuffers::ReadScalar<int> (p=0x30bd6e0) at /usr/local/include/flatbuffers/base.h:392
392 return EndianScalar(*reinterpret_cast<const T *>(p));
为什么服务器崩溃?我在做什么错,该如何解决?
P.S。
我很确定这行std::cout << ac->name()->str() << std::endl;
导致了崩溃,但是我不明白为什么。
解决方法
就像我在针对该主题打开的其他许多问题中所说的那样,您首先需要阅读FlatBuffers上的教程: Django source
一些提示:
- 您还没有完成缓冲区。
- 您实际上并没有在编写代码的任何地方使用缓冲区,只是获得缓冲区的大小。
- 您似乎在读/写时自由地混合了二进制和字符串。 FlatBuffers只需要写为二进制。像
std::hex
这样的东西用于文本输出。
提示:仅将事物放在一起而不了解它们可能会在例如Python,但会导致C ++崩溃。您需要实际学习语言和API以及它们如何工作。