Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost ASIO socket read N bytes not more not less and wait until they come or timeout exception?

Creating a simple TCP server based on examples but still do not get how to create a socket that would read some amount of bytes and if there will not be enough would wait. I need this to be NOT asynchronous operation.

#include <iostream>
#include <boost/asio.hpp>

#ifdef _WIN32
#include "Windows.h"
#endif

using namespace boost::asio::ip;
using namespace std;

int main(){
    int m_nPort = 12345;
    boost::asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), m_nPort));

    cout << "Waiting for connection..." << endl;

    tcp::socket socket(io_service);
    acceptor.accept(socket);
    cout << "connection accepted" << endl;
    try
    {
        socket.send(boost::asio::buffer("Start sending me data\r\n"));
    }
    catch(exception &e)
    {
        cerr << e.what() << endl; //"The parameter is incorrect" exception
    }
}

How to receive 10000 bytes and do it either until all 10000 arrive OR 1000 millisecond timeout and throw an exception?

like image 517
Rella Avatar asked Jul 13 '11 00:07

Rella


1 Answers

Boost 1.47.0 just introduced a timeout feature for basic_socket_iostream, namely, the expires_at and expires_from_now methods.

Here's an example based on your snippet:

#include <iostream>
#include <boost/asio.hpp>

using namespace boost::asio::ip;
using namespace std;

int main(){
    int m_nPort = 12345;
    boost::asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), m_nPort));

    cout << "Waiting for connection..." << endl;

    tcp::iostream stream;
    acceptor.accept(*stream.rdbuf());
    cout << "Connection accepted" << endl;
    try
    {
        stream << "Start sending me data\r\n";

        // Set timeout in 5 seconds from now
        stream.expires_from_now(boost::posix_time::seconds(5));

        // Try to read 12 bytes before timeout
        char buffer[12];
        stream.read(buffer, 12);

        // Print buffer if fully received
        if (stream) // false if read timed out or other error
        {
            cout.write(buffer, 12);
            cout << endl;
        }
    }
    catch(exception &e)
    {
        cerr << e.what() << endl;
    }
}

This program works for me on Linux.

Please note that I'm not advocating that you use timeouts instead of asynchronous operation with a deadline timer. It's up to you to decide. I just wanted to show that timeouts are possible with basic_socket_iostream.

like image 109
Emile Cormier Avatar answered Nov 11 '22 00:11

Emile Cormier