2016-09-30 3 views
1

クライアントファイルを受信するサーバーがありますが、外部ネットワークの転送が遅すぎるため、ファイル圧縮で解決策が見つかりました。私は圧縮のためにzlibを使用することに決めました。ドキュメントのいくつかの例で検索しましたが、私は自分のプロジェクトで使いたい2つを以下に示します。私の質問は、以下の例を使って、ファイルをディスクに保存せずに圧縮し、ソケット(クライアント側)経由で送信する方法です。ファイルを受信して​​解凍します(サーバー側)。ディスクに保存せずにzlibでファイルを圧縮し、ソケット経由で送信する

クライアントアプリケーションはWindows上で実行され、サーバーアプリケーションはLinux上で実行されます。

クライアント側:

int def(FILE *source, FILE *dest, int level) 
{ 
     int ret, flush; 
     unsigned have; 
     z_stream strm; 
     unsigned char in[CHUNK]; 
     unsigned char out[CHUNK]; 

     /* allocate deflate state */ 
     strm.zalloc = Z_NULL; 
     strm.zfree = Z_NULL; 
     strm.opaque = Z_NULL; 
     ret = deflateInit(&strm, level); 
     if (ret != Z_OK) 
      return ret; 

     /* compress until end of file */ 
     do { 
      strm.avail_in = fread(in, 1, CHUNK, source); 
      if (ferror(source)) { 
       (void)deflateEnd(&strm); 
       return Z_ERRNO; 
      } 
      flush = feof(source) ? Z_FINISH : Z_NO_FLUSH; 
      strm.next_in = in; 

      /* run deflate() on input until output buffer not full, finish 
       compression if all of source has been read in */ 
      do { 
       strm.avail_out = CHUNK; 
       strm.next_out = out; 
       ret = deflate(&strm, flush); /* no bad return value */ 
       assert(ret != Z_STREAM_ERROR); /* state not clobbered */ 
       have = CHUNK - strm.avail_out; 
       if (fwrite(out, 1, have, dest) != have || ferror(dest)) { 
        (void)deflateEnd(&strm); 
        return Z_ERRNO; 
       } 
      } while (strm.avail_out == 0); 
      assert(strm.avail_in == 0);  /* all input will be used */ 

      /* done when last data in file processed */ 
     } while (flush != Z_FINISH); 
     assert(ret == Z_STREAM_END);  /* stream will be complete */ 

     /* clean up and return */ 
     (void)deflateEnd(&strm); 
     return Z_OK; 
} 

サーバー側:

int inf(FILE *source, FILE *dest) 
{ 
    int ret; 
    unsigned have; 
    z_stream strm; 
    unsigned char in[CHUNK]; 
    unsigned char out[CHUNK]; 

    /* allocate inflate state */ 
    strm.zalloc = Z_NULL; 
    strm.zfree = Z_NULL; 
    strm.opaque = Z_NULL; 
    strm.avail_in = 0; 
    strm.next_in = Z_NULL; 
    ret = inflateInit(&strm); 
    if (ret != Z_OK) 
     return ret; 

    /* decompress until deflate stream ends or end of file */ 
    do { 
     strm.avail_in = fread(in, 1, CHUNK, source); 
     if (ferror(source)) { 
      (void)inflateEnd(&strm); 
      return Z_ERRNO; 
     } 
     if (strm.avail_in == 0) 
      break; 
     strm.next_in = in; 

     /* run inflate() on input until output buffer not full */ 
     do { 
      strm.avail_out = CHUNK; 
      strm.next_out = out; 
      ret = inflate(&strm, Z_NO_FLUSH); 
      assert(ret != Z_STREAM_ERROR); /* state not clobbered */ 
      switch (ret) { 
      case Z_NEED_DICT: 
       ret = Z_DATA_ERROR;  /* and fall through */ 
      case Z_DATA_ERROR: 
      case Z_MEM_ERROR: 
       (void)inflateEnd(&strm); 
       return ret; 
      } 
      have = CHUNK - strm.avail_out; 
      if (fwrite(out, 1, have, dest) != have || ferror(dest)) { 
       (void)inflateEnd(&strm); 
       return Z_ERRNO; 
      } 
     } while (strm.avail_out == 0); 

     /* done when inflate() says it's done */ 
    } while (ret != Z_STREAM_END); 

    /* clean up and return */ 
    (void)inflateEnd(&strm); 
    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; 
} 

答えて

1

一つの方法は、Boost Iostream compressor(彼らはZLIB、GZIP、箱から出したbzip2をサポート)と使用することですip::tcp::iostreamブーストAsioからのソケット。次のようなもの:

#include <boost/iostreams/filtering_stream.hpp> 
#include <boost/iostreams/filter/zlib.hpp> 
#include <boost/asio/ip/tcp.hpp> 

int main() { 
    boost::asio::ip::tcp::iostream connection; 

    boost::iostreams::filtering_stream<boost::iostreams::input> connection_reader; 
    connection_reader.push(boost::iostreams::zlib_decompressor()); 
    connection_reader.push(connection); 

    boost::iostreams::filtering_stream<boost::iostreams::output> connection_writer; 
    connection_writer.push(boost::iostreams::zlib_compressor()); 
    connection_writer.push(connection); 

    auto const url = "127.0.0.1"; 
    connection.connect(url, "http"); 

    // Send. 
    connection_writer << "hello there\n"; 

    // Receive. 
    for(std::string line; getline(connection_reader, line);) { 
     // Process line. 
    } 
} 
関連する問題