2016-09-30 2 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. 
    } 
}