Boost asio: можно ли превратить принятый сокет tcp в basic_socket_iostream (или каким-то образом получить его от него)? - PullRequest
6 голосов
/ 04 ноября 2011

Итак, вот моя проблема: у нас уже есть accepted надстройка asio tcp socket. И все наши API используют его. И нам просто нужно сделать такое «чтение по времени» в одной функции.

Можно выполнить такое «чтение по времени», как показано здесь . Но я получаю boost asio tcp socket от своих API, поэтому мне интересно, можно ли было как-нибудь превратить Boost :: asio socket в basic_socket_iostream . Как это сделать?

Ответы [ 3 ]

4 голосов
/ 04 ноября 2011

Интересно, можно ли как-нибудь превратить сокет Boost :: asio в basic_socket_iostream.Как это сделать?

Вы можете использовать tcp::iostream::rdbuf(), чтобы получить указатель на socket::basic_socket_streambuf затем assign() дескриптор.

#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() );
}

Хотя это очень запутанный, и я настоятельно рекомендую не идти по этому пути.Как указано ответом Ральфа и моим ответом на предложенный вами связанный вопрос, вам действительно следует использовать deadline_timer для этого.

2 голосов
/ 04 ноября 2011

Вы не утверждаете, существует ли требование не использовать асинхронные API, поэтому, возможно, это поможет вам, а может, и нет:

Если я вас неправильно понимаю, я думаю, что SO ответ, на который вы ссылаетесь, ищетв другом случае использования, т.е. время ожидания с использованием tcp :: iostream.Если вы просто хотите добавить тайм-аут к чтению, вы смотрели примеры timeout в документации по asio ?Это стандартный подход к тайм-ауту операции сокета.

1 голос
/ 30 мая 2017

Для всех, кто столкнется с этой проблемой, после нескольких часов попыток заставить это работать, я решил написать простой класс-обертку, используя 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;

};

пример использования:

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

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