Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost asio: Is it possible to turn accepted tcp socket into basic_socket_iostream (or somehow get it from it)?

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?

like image 553
Rella Avatar asked Nov 04 '11 00:11

Rella


3 Answers

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.

like image 157
Sam Miller Avatar answered Oct 16 '22 23:10

Sam Miller


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.

like image 2
Ralf Avatar answered Oct 16 '22 23:10

Ralf


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;
}
like image 1
Ray Hulha Avatar answered Oct 16 '22 22:10

Ray Hulha