chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.72k stars 1.19k forks source link

boost asio tcp connection no received data after reconnecting and reading #1444

Open guitar9 opened 3 months ago

guitar9 commented 3 months ago

I am using boost asio to connect to a TCP Server. When I run the code it works fine after start. I send the request and get the response. When I turn off the tcp server (it is a device) I am running into timeout and callback inside async_read from boost will never be executed when I am running into timeout. Then I close the socket. After turn on the device the connection could be re-established but then the recived buffer size is 0 bytes. I think thats because the async_read was not finished correctly after timeout.

header

    #include <iostream>
    #include <boost/format.hpp>
    #include <boost/asio.hpp>
    #include <boost/bind.hpp>
    #include <chrono>
    #include <thread>
    #include <future>
    #include <sstream>
    #include <iomanip>

    class TcpClient{
        public:
            int connect(boost::asio::ip::tcp::socket &socket, boost::asio::ip::tcp::endpoint &endpoint);
            int writeAndRead(boost::asio::ip::tcp::socket &socket);

    };

This is the code

  #include "tcpclient.h"

    int TcpClient::connect(boost::asio::ip::tcp::socket &socket, boost::asio::ip::tcp::endpoint &endpoint)
    {
        boost::system::error_code error;
        socket.connect(endpoint, error);
        if (!error)
        {
            std::cout << "connected" << std::endl;
            return 1;
        }
        else
        {
            std::cout << "not connected" << std::endl;
            return 0;
        }
    }

    int TcpClient::writeAndRead(boost::asio::ip::tcp::socket &socket)
    {

        boost::system::error_code error;
        auto status = std::async(std::launch::async, [&]()
                                 { boost::asio::write(socket, boost::asio::buffer("mytext"), error); })
                          .wait_for(std::chrono::milliseconds{1000});

        switch (status)
        {
        case std::future_status::deferred:
            std::cout << "std::future_status::deferred" << std::endl;
            return 0;
        case std::future_status::ready:
            std::cout << "write success" << std::endl;
            break;
        case std::future_status::timeout:
            std::cout << "std::future_status::timeout" << std::endl;
            return 0;
        }
        boost::asio::streambuf receive_buffer;
        boost::optional<boost::system::error_code> read_result;
        boost::optional<boost::system::error_code> timer_result;
        boost::asio::deadline_timer timer(socket.get_io_service());

        timer.expires_from_now(boost::posix_time::seconds(2));

        timer.async_wait([&timer_result](const boost::system::error_code &error)
                         {
            if (error != boost::asio::error::operation_aborted)
            {
                timer_result = error;
            } });

        boost::asio::async_read(socket,
                                receive_buffer,
                                boost::asio::transfer_at_least(1),
                                [&read_result](const boost::system::error_code &ec, std::size_t bytes_transferred)
                                {
                                    std::cout << "read_result: " << read_result << std::endl;
                                    read_result = ec;
                                });
        boost::system::error_code ec;

        while (1)
        {
            socket.get_io_service().reset();
            int numHandlers = socket.get_io_service().poll_one(ec);
            if (read_result)
            {
                timer.cancel();
                break;
            }
            else if (timer_result)
            {
                timer.cancel();
                std::cout << "timeout" << std::endl;
                return 0;
            }
        }
        if (receive_buffer.size() == 0)
        {
            std::cout << "receive_buffer size 0" << std::endl;
            return 0;
        }
        std::string rawResponse = boost::asio::buffer_cast<const char *>(receive_buffer.data());
        std::cout << "rawResponse: " << rawResponse << std::endl;
        return 1;
    }

    int main()
    {
        std::string ipAddress = "192.168.2.4";
        unsigned short port = 50001;
        boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(ipAddress), port);
        boost::asio::io_service ioService;
        boost::asio::ip::tcp::socket socket{ioService};
        bool isSuccess{false};
        bool isConnected{false};
        TcpClient tcpclient = TcpClient();

        while (1)
        {
            if (!isConnected)
            {
                isConnected = tcpclient.connect(socket, endpoint);
            }
            if (isConnected)
            {
                isSuccess = tcpclient.writeAndRead(socket);
                if (!isSuccess)
                {
                    std::cout << "failed close socket" << std::endl;
                    socket.close();
                    isConnected = false;
                }
                else
                {
                    std::cout << "success" << std::endl;
                }
            }
            std::cout << "wait for 1 sec" << std::endl;
            std::chrono::seconds dura(1);
            std::this_thread::sleep_for(dura);
        }

        return 0;
    }

this is the output

```
success
wait for 1 sec
write success
read_result: 0
rawResponse: 0;
success
wait for 1 sec
write success
timeout
failed close socket
wait for 1 sec
not connected
wait for 1 sec
not connected
wait for 1 sec
not connected
wait for 1 sec
not connected
wait for 1 sec
connected
write success
read_result: 0
receive_buffer size 0
failed close socket
wait for 1 sec
connected
write success
read_result: 0
receive_buffer size 0
failed close socket