深入解析 curl 的 CURLOPT_SSH_COMPRESSION:启用 SFTP/SCP 内置 SSH 压缩
【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl
导读
CURLOPT_SSH_COMPRESSION是 libcurl 中用于控制 SFTP、SCP 传输时是否启用 SSH 层内置压缩的选项。本文以 docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.md 官方文档为核心,结合本仓库 libcurl 的源码实现(setopt.c、urldata.h、vssh/libssh2.c、vssh/libssh.c)深入讲解其参数含义、底层调用链、两种 SSH 后端的差异以及命令行工具 curl 的对应用法,帮助读者在带宽受限或数据高度冗余的场景下正确开启与验证 SSH 压缩。
选项概览:NAME 与 SYNOPSIS
官方文档对该选项的定位非常明确:enable SSH compression(启用 SSH 压缩),作用于SFTP与SCP两种协议(见文档头部Protocol字段),自curl 7.56.0起加入(Added-in: 7.56.0)。
其函数原型为:
#include <curl/curl.h> CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_COMPRESSION, long enable);这是一个典型的long型开关选项,传入1L启用、0L禁用。调用后返回CURLcode,成功返回CURLE_OK (0),失败返回非零错误码,具体错误码可参考libcurl-errors(3)。
语义要点:这是一次“请求”,而非“命令”
文档的 DESCRIPTION 部分特别强调了一个容易被忽略的关键语义:
Enables built-in SSH compression. This is a request, not an order; the server may or may not do it.
即开启该选项后,libcurl 只是向 SSH 服务端发出启用压缩的协商请求,最终是否真正压缩由服务端决定,服务端有权拒绝。这与 HTTP 层的CURLOPT_ACCEPT_ENCODING(请求服务端返回压缩内容)在"协商而非强制"的哲学上是一致的,文档头部See-also也列出了CURLOPT_ACCEPT_ENCODING与CURLOPT_TRANSFER_ENCODING供对照。
另一个重要事实是默认值:DEFAULT字段明确写着0, disabled,即默认关闭,用户必须显式开启。
源码级剖析:选项如何一路传递到 SSH 会话
1. 参数存储:setopt 入口与数据结构
在 lib/setopt.c 中,选项的解析逻辑如下:
#ifdef USE_SSH case CURLOPT_SSH_COMPRESSION: s->ssh_compression = enabled; break; #endif /* !USE_SSH */两点值得注意:
- 该分支被
USE_SSH宏保护,说明只有当 libcurl 编译时启用了 SSH 支持(如配置了 libssh2 或 libssh 后端)时,该选项才可用; - 值被存入
data->set.ssh_compression,其声明位于 lib/urldata.h 的struct Curl_easy设置区:
BIT(ssh_compression); /* enable SSH compression */采用位域(BIT())存储,仅占 1 bit,与文档"长整型开关"的语义完全吻合。
2. 后端一:libssh2(LIBSSH2_FLAG_COMPRESS)
当 libcurl 使用 libssh2 作为 SSH 后端时,连接建立阶段在 lib/vssh/libssh2.c 中生效:
if(data->set.ssh_compression && libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) { infof(data, "SSH: failed to enable compression for session"); }这里调用libssh2_session_flag(..., LIBSSH2_FLAG_COMPRESS, 1)请求在会话上启用压缩;若失败,只打印一条infof级别的提示日志("SSH: failed to enable compression for session"),并不会让整个传输报错失败——这再次印证了文档所说"请求而非命令"的设计。
3. 后端二:libssh(SSH_OPTIONS_COMPRESSION 协商列表)
当使用 libssh 后端时,逻辑位于 lib/vssh/libssh.c:
if(data->set.ssh_compression) { rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_COMPRESSION, "zlib,zlib@openssh.com,none"); if(rc != SSH_OK) { failf(data, "Could not set compression"); return CURLE_FAILED_INIT; } }libssh 后端将压缩算法协商列表设为zlib,zlib@openssh.com,none:按优先级先尝试zlib(标准 RFC 压缩)、再尝试zlib@openssh.com(OpenSSH 的延迟压缩扩展)、最后兜底none。服务端从该列表中挑选其支持的算法,若只接受none,则实际不压缩。
可以看到,两个后端的共同点都是在 SSH 会话初始化阶段注入压缩标志/协商参数,且均不阻塞连接流程,完美呼应文档"server may or may not do it"的描述。
完整示例代码
官方文档给出的示例可以直接编译运行,这里完整保留并补充注释:
int main(void) { CURL *curl = curl_easy_init(); if(curl) { CURLcode result; /* 目标为 SFTP 服务器,同样适用于 scp:// 协议 */ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com"); /* 启用内置压缩(请求式协商,服务端可能拒绝) */ curl_easy_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L); /* 执行请求 */ result = curl_easy_perform(curl); curl_easy_cleanup(curl); } return 0; }注意事项:
- 请确保链接的 libcurl 启用了 SSH 后端(编译期
USE_SSH),否则该选项在curl_easy_setopt中不会生效; - 实际压缩效果取决于传输数据特征与两端算法支持情况,可通过抓包或服务端日志确认是否真正协商到压缩算法。
命令行工具 curl 的对应用法:--compressed-ssh
libcurl 的该选项在命令行工具 curl 中对应--compressed-ssh开关,其映射定义于 src/tool_getparam.c:
{"compressed-ssh", ARG_BOOL, ' ', C_COMPRESSED_SSH},并在参数处理分支 src/tool_getparam.c 中落到 libcurl 选项上。命令行用法:
curl --compressed-ssh sftp://example.com/path/to/file其详细说明见 docs/cmdline-opts/compressed-ssh.md。
使用建议与边界
- 适用场景:SSH 压缩适合高延迟、低带宽网络,或传输日志、文本、XML/JSON 等可压缩比高的数据;对已压缩的媒体文件(图片、视频、压缩包)收益有限,反而消耗 CPU。
- 默认关闭:文档明确默认值为
0,因此需要压缩时务必显式开启。 - 结果不确定:由于是协商请求,最终压缩与否取决于服务端配置(如 OpenSSH 的
Compression指令),不要假定开启后带宽一定下降。 - 版本前提:该选项自 7.56.0 起可用,老版本 libcurl 无法识别,请先通过
curl_version_info()确认版本与 SSH 后端支持情况。
参考资料
- CURLOPT_SSH_COMPRESSION 官方文档
- 选项写入实现(libssh2 分支)
- 选项存储字段定义
- libssh2 后端压缩协商
- libssh 后端压缩协商
- 命令行 --compressed-ssh 映射
- 命令行选项文档
【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考