6
votes

So here is my problem: we already have accepted a boost asio tcp socket. And all of our APIs use it. And we just need to do such 'timeouted read' in one function.

It is possible to do such 'timeouted read' as shown here. But I get boost asio tcp socket from my APIs so I wonder if it was any how possible to turn Boost::asio socket into basic_socket_iostream. How to do it?

3
Not a solution to your question, but an alternative: think-async.com/Asio/boost_asio_1_10_6/doc/html/boost_asio/…Ray Hulha

3 Answers

4
votes

I wonder if it was any how possible to turn Boost::asio socket into basic_socket_iostream. How to do it?

you can use tcp::iostream::rdbuf() to get a pointer to the socket::basic_socket_streambuf then assign() the descriptor.

#include <boost/asio.hpp>

int
main()
{
    boost::asio::io_service io_service;
    boost::asio::ip::tcp::socket socket( io_service );
    boost::asio::ip::tcp::iostream stream;
    stream.rdbuf()->assign( boost::asio::ip::tcp::v4(), socket.native_handle() );
}

Though this is very convoluted and I strongly suggest not going this route. As Ralf's answer indicated, and my answer to your linked question suggested, you really should be using a deadline_timer for this.

2
votes

You don't state whether there is a requirement not to use the asynchronous APIs so perhaps this helps you and perhaps not:

Unless I'm misunderstanding you, I think the SO answer you reference is looking at a different use case i.e. timeout using tcp::iostream. If you simply want to add a timeout to a read, have you looked at the timeout examples in the asio documentation? This is the standard approach to timeout a socket operation.

1
votes

For anyone else who will come across this problem, after trying to get this working for hours I decided to write a simple wrapper class using Boost "Devices": http://www.boost.org/doc/libs/1_64_0/libs/iostreams/doc/tutorial/container_source.html

#include <iostream>
#include <boost/smart_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/concepts.hpp> 

using boost::asio::ip::tcp;

typedef boost::shared_ptr<tcp::socket> socket_ptr;

class my_source : public boost::iostreams::source
{
public:
    my_source(socket_ptr sock) : _sock(sock)
    {

    }

    std::streamsize read(char* s, std::streamsize n)
    {
        return _sock->read_some(boost::asio::buffer(s, n));
    }

private:
    socket_ptr _sock;

};

usage example:

boost::iostreams::stream<my_source> in(sock);

for (;;) {
    std::getline(in, line);
    if (line.length() > 0)
        std::cout << line << std::endl;
    else
        break;
}