首页 > 解决方案 > 使我的函数调用 async_read 异步 Boost::asio

问题描述

我正在构建一个网络应用程序,作为 Boost asio 和整个网络的新手,我有这个疑问,这可能是微不足道的。我有这个应用程序,它从文件中读取并相应地调用 apis。我正在阅读 json (示例):

测试.json

{
    "commands":
    [
        {
            "type":"login",
            "Username": 0,
            "Password": "kk"
        }
    ]
}

我的主程序如下所示:

int main() {
    ba::io_service ios;
    tcp::socket s(ios);
    s.connect({{},8080});

    IO io;
    io.start_read(s);
    io.interact(s);
    

    ios.run();
}
void start_read(tcp::socket& socket) {
        char buffer_[MAX_LEN];
        socket.async_receive(boost::asio::null_buffers(),
                [&](const boost::system::error_code& ec, std::size_t bytes_read) {
                    (void)bytes_read;
                    if (likely(!ec)) {
                        boost::system::error_code errc;
                        int br = 0;
                        do {
                            br = socket.receive(boost::asio::buffer(buffer_, MAX_LEN), 0, errc);
                            if (unlikely(errc)) {
                                if (unlikely(errc != boost::asio::error::would_block)) {
                                    if (errc != boost::asio::error::eof)
                                        std::cerr << "asio async_receive: error " << errc.value() << " ("
                                                            << errc.message() << ")" << std::endl;
                                    interpret_read(socket,nullptr, -1);
                                    //close(as);
                                    return;
                                }
                                break; // EAGAIN
                            }
                            if (unlikely(br <= 0)) {
                                std::cerr << "asio async_receive: error, read " << br << " bytes" << std::endl;
                                interpret_read(socket,nullptr, br);
                                //close(as);
                                return;
                            }
                            interpret_read(socket,buffer_, br);
                        } while (br == (int)MAX_LEN);
                    } else {
                        if (socket.is_open())
                            std::cerr << "asio async_receive: error " << ec.value() << " (" << ec.message() << ")"
                                                << std::endl;
                        interpret_read(socket,nullptr, -1);
                        //close(as);
                        return;
                    }
                    start_read(socket);
                });
    }
    void interpret_read(tcp::socket& s,const char*  buf, int len) {

        if(len<0)
        {
            std::cout<<"some error occured in reading"<<"\n";
        }
        const MessageHeaderOutComp *obj = reinterpret_cast<const MessageHeaderOutComp *>(buf);
        int tempId = obj->TemplateID;
        //std::cout<<tempId<<"\n";
        switch(tempId)
        {
            case 10019: //login
            {
                //const UserLoginResponse *obj = reinterpret_cast<const UserLoginResponse *>(buf);
                std::cout<<"*********[SERVER]: LOGIN ACKNOWLEDGEMENT RECEIVED************* "<<"\n";
                break;
            }
        }
        std::cout << "RX: " << len << " bytes\n";
        if(this->input_type==2)
            interact(s);
    }

    void interact(tcp::socket& s)
    {
        if(this->input_type == -1){
            std::cout<<"what type of input you want ? option 1 : test.json / option 2 : manually through command line :";
            int temp;
            std::cin>>temp;
            this->input_type = temp;
        }
        if(this->input_type==1)
        {
            //std::cout<<"reading from file\n";
            std::ifstream input_file("test.json");
            Json::Reader reader;
            Json::Value input;
            reader.parse(input_file, input);
            for(auto i: input["commands"])
            {
                std::string str = i["type"].asString();
                if(str=="login")
                    this->login_request(s,i);
            }
            std::cout<<"File read completely!! \n Do you want to continue or exit?: ";
        }
    }

发送工作正常,消息被发送并且服务器以正确的方式响应,但我需要理解的是为什么控件不去on_send_completed(打印发送的 x 字节)。它也不会打印消息[SERVER]: LOGIN ACKNOWLEDGMENT RECEIVED,我知道我缺少一些基本的东西或做错了什么,请纠正我。

login_request 函数:

void login_request(tcp::socket& socket,Json::Value o) {
        
        /*Some buffer being filled*/

        async_write(socket, boost::asio::buffer(&info, sizeof(info)), on_send_completed);
    }

提前致谢!!

标签: c++socketsnetworkingboostboost-asio

解决方案


从粗略的扫描来看,您似乎重新定义buffer_了已经是一个类成员(IO大概是)。

它被本地 in 隐藏start_read,它既是 UB(因为生命周期在异步读取操作完成之前结束),也使得它_buffer不使用成员。

我看到很多令人困惑的代码。为什么要从完成处理程序中进行同步读取?

我认为您可能正在寻找组合操作读取(boost::asio::async_read 和 boost::asio::async_until)


推荐阅读