2010-08-05 37 views
0

Je travaille sur une application où j'ai besoin d'envoyer un "nom de fichier", "filesize" et les fichiers sur le réseau. J'ai créé un serveur en utilisant boost qui, pour l'instant, lit dans la taille du fichier et le nom. Je me demande comment je peux remplir un tampon avec les données du fichier (si nécessaire) et comment le transférer au serveur.C++, boost: comment remplir le tampon et transférer des données de fichier (image) sur le réseau?

C'est ce que j'ai maintenant:

#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 

Répondre

1

Que diriez-vous du dumping juste le fichier sur le fil? C'est comme ça que le fait HTTP. En fait, je vois que vous utilisez presque le même protocole que HTTP. Envoyez toutes les métadonnées sous forme de texte clair premier (nom, taille, etc.), mis en une ligne vide comme terminaison pour les métadonnées (\ r \ n) et maintenant tout ce que vous avez besoin est de vider le fichier lui-même:

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; 
    } 
} 
+0

Salut Gianni, merci beaucoup pour votre réponse! Est-ce que cela enverra correctement toutes les données? Ou est-ce que toutes les données sont envoyées en morceaux et ai-je besoin d'appeler async_write() plusieurs fois avec des morceaux? – pollux

+0

Cela devrait toutes les données. Pas besoin de rien d'autre vraiment. – Gianni

+0

Salut Gianni, je vais essayer demain .. mon code est au travail. Mais merci beaucoup! Je ne m'attendais pas à être si facile! – pollux