C++ zLib与Qt C++;MCCP/Telnet压缩2选项

C++ zLib与Qt C++;MCCP/Telnet压缩2选项,c++,qt,telnet,zlib,C++,Qt,Telnet,Zlib,我正在尝试压缩/解压缩QString 如何设置:有一个telnet/socket模块,用于从telnet服务器读取信息。然后将这些字符串发送到Javascript(这是一个think客户端,用户界面使用QWebView等在HTML中实现)。这很好用 我想添加对MCCP(输入/输出的zlib压缩)的支持 我希望,如果可能的话,允许对脚本的完全脚本支持(只有最小的C++代码,其他所有的插件都是通过插件实现的) 我想实现两个函数,compressString和decompressString: QSt

我正在尝试压缩/解压缩QString

如何设置:有一个telnet/socket模块,用于从telnet服务器读取信息。然后将这些字符串发送到Javascript(这是一个think客户端,用户界面使用QWebView等在HTML中实现)。这很好用

我想添加对MCCP(输入/输出的zlib压缩)的支持

我希望,如果可能的话,允许对脚本的完全脚本支持(只有最小的C++代码,其他所有的插件都是通过插件实现的) 我想实现两个函数,compressString和decompressString:

QString MainWindow::compressString(QString s) {

    QByteArray str = s.toLocal8Bit();

    int ret,flush;
    z_stream strm;
    unsigned char out[CHUNK];
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    ret = deflateInit(&strm,Z_DEFAULT_COMPRESSION);
    if ( ret != Z_OK ) {
        return "ERROR: Failed to init z_stream";
    }
    // do until end of string
    do {
       strm.avail_in = str.size();
       strm.next_in = (unsigned char*)str.data();
       strm.avail_out = CHUNK;
       strm.next_out = out;
       flush = Z_FINISH;
       ret = deflate(&strm,flush);
       if ( ret == Z_STREAM_ERROR) {
           return "ERROR: Z_STREAM_ERROR when deflating.";
       }
    } while ( flush != Z_FINISH );
    deflateEnd(&strm);
    return QString( (char *)out );
}
QString MainWindow::decompressString(QString s) {
    QByteArray str = s.toLocal8Bit();

    int ret,flush;
    z_stream strm;
    unsigned char out[CHUNK];
    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 "ERROR: Failed to init z_stream for inflate";
    }
    // do until end of string
    do {
       strm.avail_in = str.size();
       strm.next_in = (unsigned char*)str.data();
       strm.avail_out = CHUNK;
       strm.next_out = out;
       flush = Z_NO_FLUSH;
       ret = inflate(&strm,flush);
       if ( ret == Z_STREAM_ERROR) {
           return "ERROR: Z_STREAM_ERROR when inflating.";
       }
       switch( ret ) {
        case Z_NEED_DICT:
           inflateEnd(&strm);
           return "Error: Z_NEED_DICT";
           break;
        case Z_DATA_ERROR:
           inflateEnd(&strm);
           return "Error: Z_DATA_ERROR";
           break;
        case Z_MEM_ERROR:
           inflateEnd(&strm);
           return "Error: Z_MEM_ERROR";
           break;
        default:
           break;
       }
    } while ( ret != Z_STREAM_END );
    inflateEnd(&strm);

    return QString( (char *)out );
}
这是我试过的第三次/第四次重写。压缩字符串方法返回以下内容:xóHÍÉWÏ/IQ 也许是对的,也许不是,我不知道

decompressString方法返回以下结果:错误:Z_NEED_DICT

不管我做什么(我已经尝试了在web上和堆栈溢出上找到的一些其他示例)

现在我只是输入JS中的字符串,最终我想使用telopt 86压缩/解压缩从telnet服务器发送的字符串

如有任何帮助/建议,将不胜感激。我现在的目标只是准备一个简单的输入/输出测试

更新:

查看zlib充气代码后,我的问题是:

state->mode = hold & 0x200 ? DICTID : TYPE;
Zlib希望字符串上有某种类型的头
hold
是缓冲区,dictd将其发送到所需的Z_DICT_请求。这很可能是因为头不在那里,或者在字符串传递时丢失了头。如果我破解它并说
state->mode=TYPE然后我将得到一个数据错误

此外,我更改了解压缩功能,如下所示:

QString MainWindow::decompressString(QString s) {
    QByteArray str = s.toLocal8Bit();

    unsigned char in[CHUNK];
    for ( int i = 0; i < str.size(); i++ ) {
        in[i] = (unsigned char)str.at(i);
    }
    fflush(stdout);
    int ret,flush;
    z_stream strm;
    unsigned char out[CHUNK];
    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 "ERROR: Failed to init z_stream for inflate";
    }
    // do until end of string
    do {
       strm.avail_in = str.size();
       strm.next_in = in;
       strm.avail_out = CHUNK;
       strm.next_out = out;
       flush = Z_NO_FLUSH;
       ret = inflate(&strm,flush);
       if ( ret == Z_STREAM_ERROR) {
           return "ERROR: Z_STREAM_ERROR when inflating.";
       }
       switch( ret ) {
        case Z_NEED_DICT:
           inflateEnd(&strm);
           return "Error: Z_NEED_DICT";
           break;
        case Z_DATA_ERROR:
           inflateEnd(&strm);
           return "Error: Z_DATA_ERROR";
           break;
        case Z_MEM_ERROR:
           inflateEnd(&strm);
           return "Error: Z_MEM_ERROR";
           break;
        default:
           break;
       }
    } while ( ret != Z_STREAM_END );
    inflateEnd(&strm);

    return QString( (char *)out );
}
QString主窗口::解压缩字符串(QString s){
QByteArray str=s.toLocal8Bit();
[CHUNK]中的未签名字符;
对于(int i=0;i

然后对deflate生成的输出使用printf,然后发送给充气的内容和数据(每个字符的十六进制值)看起来是相同的。

基本上,您不能

qString“丢失”了一些数据。为了使用zlib进行压缩/解压缩,您需要使用QByteArray,事实上,如果您只使用STL字符串,并且只在需要时转换为QByteArray,则更容易。我发现有效的解决方案来自pantehma.net

因为我是从外部源读取压缩字符串,所以我不会将它们转换为qString并在C层处理压缩/解压缩,也不会麻烦将其传递给javascript。这根本不值得花那么多精力让它发挥作用


祝投票否决该问题的人圣诞快乐。

检查out缓冲区似乎表明,在deflate生成的null之后有大约4个字节的数据。我可能必须用toString方法将其实现为一个QObject,以便维护一个可以传递的字节缓冲区?不知道如何只使用qstring来实现这一点。在
(de)压缩的
函数中,您在循环中使用
out
In
缓冲区,而不推进它。如果循环迭代超过一次,这将覆盖任何以前的数据。也许压缩函数会这样,因此你会丢失字典。这不应该影响in,这就是dict的位置。不?缓冲区如此之大,字符串如此之小,它不应该循环…块是巨大的,就像16千字节。我的计划是允许JS层/插件选择进行MCCP,但也许我会将它放在C层,当它通过电线时解压QByteArray内容。这可能更容易。