Boost ASIO-TCP数据包的无效标题和正文

问题描述

我将Boost ASIO用作项目的TCP网络通信解决方案。

这是我的代码:

Client.h

namespace Vibranium{
    class Client: public std::enable_shared_from_this<Client>
    {
    public:
        Client(tcp::socket socket)
        : socket(std::move(socket))
        {
        }
        void start();
        int connectionId;
        tcp::socket socket;
        void Send(ServerOpcode serverOpcode,const std::string& message);

    private:
        void read_header();
        void read_body();
        Packet _packet;
    };
}
#endif //VIBRANIUM_CORE_CLIENT_H

这是我阅读标题和正文的方式:

void Vibranium::Client::read_header() {
    auto self(shared_from_this());
    boost::asio::async_read(socket,boost::asio::buffer(_packet.data_,_packet.header_length),[this,self](boost::system::error_code ec,std::size_t /*length*/)
    {
        if (!ec)
        {
            std::cout << "Header: " << std::endl;
            std::cout.write(_packet.data_,_packet.header_length);
            std::cout << "\n";
            read_body();
        }
        else
        {
            std::cerr << "Invalid header sent!" << std::endl;
        }
    });
}


void Vibranium::Client::read_body() {
    auto self(shared_from_this());
    socket.async_read_some(boost::asio::buffer(_packet.data_,_packet.body_length),std::size_t length)
   {
       if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec))
       {
           Logger::Log("Disconnected ID: " + std::to_string(connectionId),Logger::Error,true);
           for (int i = 0; i < Server::Clients.size(); ++i) {
               if(Server::Clients[i]->connectionId == connectionId)
                   Server::Clients.erase(Server::Clients.begin()+i);
           }
       }
       else
       {
           std::cout << "Body: " << std::endl;
           std::cout.write(_packet.data_,_packet.body_length);
           std::cout << "\n";
           //Send(ServerOpcode::SMSG_AUTH_CONNECTION_RESPONSE,"How are you,mate?");
           read_header();
       }
   });
}

这是我发送带有标题和正文的消息的方式:

Config config("AuthServer");
std::string defaultIP   = "127.0.0.1";
std::string defaultPort = "8080";
int connectionsNumber   = CommandQuestion<int>::AskQuestion("How many connections do you want established?");
std::cout << "Initializing " << std::to_string(connectionsNumber) << " connection/s." << std::endl;

std::cout << "Trying to connect to  " <<  defaultIP << " on port: " << config.GetConfigValue("AuthServerPort",defaultPort)  << std::endl;
boost::asio::io_context io_context;
std::vector<tcp::socket> sockets;
for (int i = 0; i < connectionsNumber; ++i) {
    try
    {
        sockets.emplace_back(io_context);
        tcp::socket& s{sockets.back()};
        tcp::resolver resolver(io_context);
        boost::asio::connect(s,resolver.resolve( defaultIP,config.GetConfigValue("AuthServerPort",defaultPort)));

        enum { body_length = 1024 };
        enum { header_length = 8 };
        enum { max_length = body_length +  header_length};
        char header_[header_length];
        char body_[body_length];
        char data_[header_length + body_length];

        ServerOpcode opc;
        opc = ServerOpcode::SMSG_AUTH_CONNECTION_RESPONSE;
        std::string message = "I am testing here!!!";


        snprintf(header_,header_length,"%x\n",opc);
        strcpy(body_,message.c_str());
        sprintf(data_,"%s %s",header_,body_);

        size_t request_length = sizeof(data_)/sizeof(*data_);

        std::cout << "header: " << header_ << std::endl;
        std::cout << "body: " << body_ << std::endl;
        std::cout << "whole message is: " << data_ << std::endl;
        std::cout << "size: " << request_length << std::endl;
        std::cout << "max size: " << max_length << std::endl;

        boost::asio::write(s,boost::asio::buffer(data_,request_length));
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }

}

这是服务器上的输出:

New Connection (ID: 1)
Header: 
1
 I am 
Body: 
testing here!!!
hP��U��TK���U�U�� K�h
�*�� K�) �J�Uh
 0�y���x������������RK�Px���� K��RK�`x��\TUK��TK��;�#K��TJ�d�"K��XUK�v\TUK� �TK�{�|@X#K� �TJ�`FK��XUK��\TUK� �TK��G�|X^#K� �TJ�4AK��XUK�:\TUK��TK�z���M$K��TJ���#K��XUK��
u��u�z��x�TK��u��<}(K�@u��Pu���aUK��TJ��TK������TJ��TK�x�TK���U�{��������UK��M$K��TK����@K��{����UK�
Invalid header sent!

这是客户端上的输出:

header: 1

body: I am testing here!!!
whole message is: 1
 I am testing here!!!
size: 1032
max size: 1032

Process finished with exit code 15

为了避免这个问题被代码淹没,这里是Packet.hhttps://pastebin.com/cnNzpRpVPacket.cpphttps://pastebin.com/mbZPxf4e

的内容

我看到的是报头和正文都以某种方式传输了,但是它们没有正确解析。为什么我在服务器上收到这样的格式错误的输出?我的错误在哪里,如何解决?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)