2016-09-30 29 views
1

我有一臺接收客戶端文件的服務器,但是外部網絡中的傳輸速度太慢,讀了一會兒,我發現文件壓縮的​​解決方案。我決定使用zlib進行壓縮,我在文檔中的一些示例中進行了搜索,下面是我希望在我的項目中使用的兩個示例。我的問題是,如何使用以下示例來壓縮文件而不保存到磁盤並通過套接字(客戶端)發送。並接收並解壓文件(服務器端)。使用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來自Boost 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. 
    } 
}