Melissia_M Melissia_M - 2 months ago 41
C++ Question

Reading and writing files with boost iostream socket

I'm trying to send and receive files using boost iostream sockets. what is the most efficient way to read the contents of the file and then send to stream? And how to read this content on the server side and write to file?

Send:

boost::asio::io_service svc;
using boost::asio::ip::tcp;
tcp::iostream sockstream(tcp::resolver::query{ "127.0.0.1", "3780" });

std::ifstream fs;
fs.open("img.jpg", std::ios::binary);
sockstream << // send file to stream


Receive:

boost::asio::io_service ios;

boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 3780);
boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);

for (;;)
{
boost::asio::ip::tcp::iostream stream;
boost::system::error_code ec;
acceptor.accept(*stream.rdbuf(), ec);

if (!ec) {
std::ofstream of;
of.open("rcv.jpg", std::ios::binary);

// read the file content with stream
// write content to file
}
}

Answer

I filled in the missing pieces from the documentation example:

http://www.boost.org/doc/libs/1_62_0/doc/html/boost_asio/example/cpp03/iostreams/daytime_server.cpp

Here's a simple sender/receiver program that (I think) does what you expect:

Live On Coliru

#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <fstream>
using boost::asio::ip::tcp;

void sender() {
    boost::asio::io_service svc;

    tcp::iostream sockstream(tcp::resolver::query { "127.0.0.1", "6768" });

    boost::iostreams::filtering_ostream out;
    out.push(boost::iostreams::zlib_compressor());
    out.push(sockstream);

    {
        std::ifstream ifs("main.cpp", std::ios::binary); // pretend this is your JPEG
        out << ifs.rdbuf();
        out.flush();
    }
}

void receiver() {

    int counter = 0;
    try
    {
        boost::asio::io_service io_service;

        tcp::endpoint endpoint(tcp::v4(), 6768);
        tcp::acceptor acceptor(io_service, endpoint);

        for (;;)
        {
            tcp::iostream stream;
            boost::system::error_code ec;
            acceptor.accept(*stream.rdbuf(), ec);

            {
                boost::iostreams::filtering_istream in;
                in.push(boost::iostreams::zlib_decompressor());
                in.push(stream);

                std::ofstream jpg("test" + std::to_string(counter++) + ".out", std::ios::binary);
                copy(in, jpg);
            }

            // break; // just for shorter demo
        }
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
        exit(255);
    }
}

int main(int argc, char**argv) {
    if (--argc && argv[1]==std::string("sender"))
       sender();
    else
       receiver();
}

When you run the receiver:

./test

And use the sender several times:

./test sender

The receiver will decompress and write the file received to test0.out, test1.out etc.