c ++, boost: как заполнить буфер и передать (файл) данные файла по сети? - PullRequest
0 голосов
/ 05 августа 2010

Я работаю над приложением, в котором мне нужно отправить «имя файла», «размер файла» и данные файла по сети. Я создал сервер с помощью boost, который пока что читает размер файла и имя.

Мне интересно, как я могу заполнить буфер данными файла (при необходимости) и как перенести его на сервер.

Вот что у меня сейчас:

#ifndef OFXFILETRANSFERSENDH
#define OFXFILETRANSFERSENDH

#undef check // necessary to get Boost running on Mac

#include <vector> 
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

#include "ofxFileTransferConnection.h"
using boost::asio::ip::tcp;
class ofxFileTransferSend : public boost::enable_shared_from_this<connection> {
public:
    typedef boost::shared_ptr<ofxFileTransferSend> pointer;
    static pointer create(
                        boost::asio::io_service& rIOService
                        ,std::string sServer
                        ,const char* sPort) 
    {
        return pointer(new ofxFileTransferSend(rIOService,sServer, sPort));
    }


private:
    //--------------------------------------------------------------
    ofxFileTransferSend(
                    boost::asio::io_service &rIOService
                    ,const std::string sServer
                    ,const char* sPort
    )
        :port(sPort)
        ,socket_(rIOService)
        ,resolver_(rIOService)
    {

        tcp::resolver::query query(sServer, sPort);
        resolver_.async_resolve(
                            query
                            ,boost::bind(
                                    &ofxFileTransferSend::handleResolve
                                    ,this
                                    ,boost::asio::placeholders::error
                                    ,boost::asio::placeholders::iterator
                            )
        );
    }


    //--------------------------------------------------------------
    void handleResolve(
        const boost::system::error_code &rError
        ,tcp::resolver::iterator oEndPointIterator
    )
    {
        if (!rError) {
            tcp::endpoint end_point = *oEndPointIterator;
            socket_.async_connect(
                                end_point
                                ,boost::bind(
                                    &ofxFileTransferSend::handleConnect
                                    ,this
                                    ,boost::asio::placeholders::error
                                    ,++oEndPointIterator
                                )
            );
        }
        else {
            std::cout << "Error while resolving server: " << std::endl;
        }
    }

    //--------------------------------------------------------------
    void handleConnect(
        const boost::system::error_code &rError
        ,tcp::resolver::iterator rOEndPointIterator
    )
    {
        if(!rError) {
            std::cout << "Connected to remote server!" << std::endl;
            std::size_t size = 1235;
            std::ostream send_data_stream(&send_data);
            send_data_stream << "filename.jpg" << "\r\n";
            send_data_stream << size << "\r\n";

            boost::asio::async_write(
                            socket_
                            ,send_data
                            ,boost::bind(
                                &ofxFileTransferSend::handleSendFileInfo
                                ,this
                                ,boost::asio::placeholders::error
                            )
            );
        }
        else {
            // @todo on failure retry!
            std::cout << "Error connecting to ofxFileTransferServer:" << rError.message()<< std::endl;
        }
    }


    //--------------------------------------------------------------
    void handleSendFileInfo(
        const boost::system::error_code &rError
    )
    {
        if(!rError) {
            cout << "okay nice, send file data done!\n";
        }
        else {
            std::cout << "Error sending file info: " << rError.message() << std::endl;
        }
    }   

    tcp::resolver resolver_;
    tcp::socket socket_;
    boost::asio::streambuf send_data;
    const char* port;
};
#endif

1 Ответ

1 голос
/ 05 августа 2010

Как насчет простого сброса файла на провод?Вот как это делает HTTP.На самом деле, я вижу, что вы используете почти тот же протокол, что и HTTP.Сначала отправьте все метаданные в виде открытого текста (имя, размер и т. Д.), Поместите пустую строку в качестве терминатора для метаданных (\ r \ n), и теперь все, что вам нужно, - это сбросить сам файл:

void handleSendFileInfo(
    const boost::system::error_code &rError
)
{
    if(!rError) {
        std::ofstream fileData(fileName);

        boost::asio::async_write(
                        socket_
                        ,fileData
                        ,boost::bind(
                            &ofxFileTransferSend::handleSendFileData
                            ,this
                            ,boost::asio::placeholders::error
                        )
        );
    }
    else {
        std::cout << "Error sending file info: " << rError.message() << std::endl;
    }
}   
...