简体   繁体   中英

Making my function which calls async_read asynchronous Boost::asio

I am building an networking application, and being a newbie to Boost asio and networking as a whole had this doubt which might be trivial. I have this application which reads from a file and calls apis accordingly. I am reading json (example):

test.json

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

My main program looks like this:

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?: ";
        }
    }

The sending works fine, the message is sent and the server responds in a correct manner, but what I need to understand is why is the control not going to on_send_completed (which prints sent x bytes). Neither it prints the message [SERVER]: LOGIN ACKNOWLEDGEMENT RECEIVED , I know I am missing something basic or am doing something wrong, please correct me.

login_request function:

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

Thanks in advance!!

From a cursory scan it looks like you redefined buffer_ that was already a class member (of IO , presumably).

It's hidden by the local in start_read , which is both UB (because the lifetime ends before the async read operation completes) and also makes it so the member _buffer isn't used.

I see a LOT of confusing code though. Why are you doing synchronous reads from within completion handlers?

I think you might be looking for the composed-ooperation reads (boost::asio::async_read and boost::asio::async_until)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM