4 Stimmen

Gibt es ein boost::iostreams (bidirektionales) Gerät für eine blockierende boost::asio TCP-Verbindung?

Ich untersuche C++-Bibliotheken für portablen, blockierenden E/A-Zugriff auf das Dateisystem und das Netzwerk. Es siehe きにめす boost::filesystem , boost::iostreams y boost::asio werden zu dritt die Arbeit erledigen.

Um es klarzustellen, ich bin derzeit nicht an den asynchronen Aspekten von boost::asio Ich möchte nur eine tragbare, blockierende Schnittstelle zum Netz.

Wenn ich mich umschaue, sehe ich boost::iostreams hat einen Begriff von Geräten, von denen jedes eine zugehörige Moduskonzept . Der bidirektionale Modus scheint speziell auf den Streaming-Zugang zu einer Vollduplex-TCP-Verbindung zugeschnitten zu sein. Fantastisch.

boost::iostreams scheint keine Unterstützung für das tatsächliche Öffnen von TCP-Verbindungen zu bieten (im Gegensatz zum lokalen Dateisystem.) Das ist in Ordnung, denn boost::asio kann ich die Verbindung öffnen und sie als bidirektionale Verbindung modellieren. Device und wickeln Sie es in ein boost::iostreams::stream .

außer es wird nicht? Ich sehe boost::asio::ip::tcp::iostream , die die boost::iostreams::stream aber vermutlich nicht als Device .

Ich verstehe die tcp::iostream würde sich ähnlich verhalten, aber ich würde es trotzdem vorziehen, nur für eine Schnittstelle zu lernen und zu programmieren, nicht für zwei. Insbesondere der Umgang mit zwei Fehlerbehandlungssystemen und Ausnahmehierarchien ist nicht sehr schmackhaft.

Die Frage ist also: Bin ich blind? Vielleicht gibt es einen Adapter zwischen den beiden Bibliotheken, den ich beim Herumgoogeln übersehen habe. Oder vielleicht hat jemand bereits einen solchen Adapter als 3rd-Party-Komponente, die ich in fallen könnte freigegeben?

7voto

Dave S Punkte 19802

Eine direkte Zuordnung ist mir nicht bekannt. Wenn Sie jedoch daran interessiert sind, ist es ziemlich einfach, ein solches Gerät zu schreiben. Diese Version wirft boost::system::system_error für Nicht-EOF-Fehler, aber Sie können auch etwas anderes tun.

#include <iosfwd>

#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/iostreams/categories.hpp>
#include <boost/system/system_error.hpp>

class asio_stream_device
{
public:
    typedef char char_type;
    typedef boost::iostreams::bidirectional_device_tag category;

    explicit asio_stream_device(boost::asio::ip::tcp::socket& sock) : socket_(sock)
    {

    }

    std::streamsize read(char* s, std::streamsize n)
    {
        // Read up to n characters from the underlying data source
        // into the buffer s, returning the number of characters
        // read; return -1 to indicate EOF
        boost::system::error_code ec;

        std::size_t rval = socket_.read_some(boost::asio::buffer(s, n), ec);
        if (!ec)
        {
            return rval;
        }
        else if (ec == boost::asio::error::eof)
        {
            return -1;
        }
        else
        {
            throw boost::system::system_error(ec,"read_some");
        }

    }

    std::streamsize write(const char* s, std::streamsize n)
    {
        // Write up to n characters to the underlying
        // data sink into the buffer s, returning the
        // number of characters written

        boost::system::error_code ec;
        std::size_t rval = socket_.write_some(boost::asio::buffer(s, n), ec);
        if (!ec)
        {
            return rval;
        }
        else if (ec == boost::asio::error::eof)
        {
            return -1;
        }
        else
        {
            throw boost::system::system_error(ec,"write_some");
        }

    }

private:

    boost::asio::ip::tcp::socket& socket_;

};

Im Grunde öffnen/verbinden Sie den Socket wie gewohnt und übergeben ihn dann an den Konstruktor. Das Beispiel liest einfach und gibt auf dem Bildschirm aus.

void test
{
   namespace asio = boost::asio;
   namespace io = boost::iostreams;

   asio::io_service service;
   asio::ip::tcp::socket socket(service);

   asio::ip::tcp::endpoint remote -  ...; ////

   socket.connect(remote);

   io::stream<asio_stream_device> str(socket);

   std::string line;

   while (std::getline(str, line)) {
    std::cout << line << std::endl;
   }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X