Timeouts on read and writes

I have been searching for a way to cancel a Boost ASIO read or write operation if it takes over a certain amount of time. My server is sending out HTTP requests, and reading results from those requests, so I originally had coded it as a synchronous read/write, and if it took so long, I would just carry on and ignore the results when they came back. This caused a problem if a server went down, my server would open to many sockets, and would crash. So I decided that I wanted to cancel the read/write if there was too long of a delay, but apparently synchronous read/writes are not able to be canceled without destroying the thread they are running in, which I do not want to do. So I found a post about how to mimic a synchronous read/write with asynchronous calls and cancel a call on time out. This is the post that I followed. I know this post is fairly old, so I am not sure if function calls have change since that version and the one I am working with(1.48), but this doesn't seem to be working quite right. Here is my code

bool connection::query_rtb(const std::string &request_information, std::string &reply_information)
{
    try
    {
        boost::optional<boost::system::error_code> timer1_result, timer2_result, write_result, read_result;
        boost::array<char,8192> buf;
        buf.assign(0);

        boost::asio::deadline_timer dt(io_service_);
        dt.expires_from_now(boost::posix_time::milliseconds(100));
        dt.async_wait(boost::bind(&connection::set_result, this, &timer1_result, _1, "timer1"));
        boost::asio::async_write(socket_, boost::asio::buffer(request_information, request_information.size()), boost::bind(&connection::set_result, this, &write_result, _1, "write"));
        io_service_.reset();

        while(io_service_.run_one())
        {
            if(write_result)
            {
                dt.cancel();
            }
            else if(timer1_result)
            {
                socket_.cancel();
            }
        }


        boost::asio::deadline_timer dt2(io_service_);
        dt2.expires_from_now(boost::posix_time::milliseconds(3000));
        dt2.async_wait(boost::bind(&connection::set_result, this, &timer2_result, _1, "timer2"));
        boost::asio::async_read(socket_, boost::asio::buffer(buf), boost::bind(&connection::set_result, this, &read_result, _1, "read"));
        //socket_.async_receive(boost::asio::buffer(buf), boost::bind(&connection::set_result, this, &read_result, _1, "read"));

        io_service_.reset();
        while(io_service_.run_one())
        {
            if(read_result)
            {
                dt2.cancel();
            }
            if(timer2_result)
            {
                socket_.cancel();
            }
        }


        reply_information = buf.data();
        std::cout << reply_information << std::endl;
        return true;
    }catch(std::exception& e)
    {
         std::cerr << e.what() << std::endl;
    }
}

void persistent_connection::set_result(boost::optional<boost::system::error_code> *a, boost::system::error_code ec, std::string t)
{
    std::cout << t << std::endl;
    a->reset(ec);
}

I was wondering if anyone see anything wrong with this code, or has any ideas on why it is not working. Currently the write seems to be fine, however the will not read until after the dt2 is done with it's timer. Please let me know if you need any more information, I will be glad to provide some.

Edit:

Seems like I got it working testing something I thought I previously tested. Using async_receive instead of async_read seems to have fixed whatever problem I was having. Any clue why this would cause I problem? I want to know if there is a problem with my logic or if that is how is async_read will usually act.

Answers


boost::array<char,8192> buf;

...

boost::asio::async_read(socket_, boost::asio::buffer(buf), boost::bind(&connection::set_result, this, &read_result, _1, "read"));

You have instructed your program to read 8192 bytes from the socket. If switching the logic from using the async_read() free function to the async_receive() member function resolves this problem, consult the documentation

Remarks

The receive operation may not receive all of the requested number of bytes. Consider using the async_read function if you need to ensure that the requested amount of data is received before the asynchronous operation completes.


Need Your Help

How to copy text to system clipboard in emacs while working in terminal buffer?

linux osx emacs clipboard

I usually use emacs in a text terminal environment to manipulate text. In some particular situations, however, I want to interact with the system's clipboard, for example, copy text from emacs to a

Drupal 6 - creating full page content with no sidebars within

drupal-6 drupal-blocks

Hi im trying to create full page content with no sidebars within Drupal 6. I have created a Block that takes up the full page and turned off other blocks but by any chance does someone know how to ...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.