libssh实现SFTP文件传输速度远低于同类工具,如何优化?
优化方案
你遇到的速度差主要是libssh默认参数未针对大文件传输优化、同步读写引入大量RTT开销导致的,按以下优先级调整即可追平甚至超过主流工具的传输速度:
1. 调大SSH接收窗口
libssh默认的TCP接收窗口极小,是速度慢的核心原因,在初始化SSH会话时添加窗口配置:
// 放在ssh_connect之前添加 uint32_t recv_window = 2 * 1024 * 1024; // 设置2MB接收窗口,可根据网络环境调整到1~4MB ssh_options_set(my_ssh_session, SSH_OPTIONS_RECV_WINDOW, &recv_window);
这一步调整后通常就能把速度提升3~5倍。
2. 更换为更快的加密算法
默认的加密算法优先级可能选择了算力开销更高的方案,手动指定硬件加速的轻量加密算法:
// 同样放在ssh_connect之前添加 const char* ciphers = "aes128-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-gcm@openssh.com"; ssh_options_set(my_ssh_session, SSH_OPTIONS_CIPHERS_C_S, ciphers); ssh_options_set(my_ssh_session, SSH_OPTIONS_CIPHERS_S_C, ciphers);
如果你的CPU支持AES指令集,aes-gcm系列算法的加密开销可以忽略不计。
3. 替换同步sftp_read为异步AIO读写
你现在用的同步读逻辑是发一个读请求、等结果返回、再发下一个,每一次请求都要等网络往返延迟,带宽根本打不满。改用libssh提供的异步AIO接口批量发读请求,就能消除RTT开销:
// 示例逻辑,可根据需要调整并发请求数 #define AIO_PARALLEL 8 #define AIO_BUF_SIZE (128 * 1024) sftp_aio_handle aio_handles[AIO_PARALLEL]; char aio_buffers[AIO_PARALLEL][AIO_BUF_SIZE]; // 先批量发读请求 for (int i = 0; i < AIO_PARALLEL; i++) { aio_handles[i] = sftp_aio_read(file, aio_buffers[i], AIO_BUF_SIZE); if (aio_handles[i] == NULL) { // 错误处理 } } // 循环收结果,同时发新请求 int pending = AIO_PARALLEL; while (pending > 0) { sftp_aio_wait(aio_handles, pending, NULL); for (int i = 0; i < pending; i++) { if (sftp_aio_is_finished(aio_handles[i])) { ssize_t nread = sftp_aio_get_return_code(aio_handles[i]); if (nread > 0) { write(fd, aio_buffers[i], nread); // 发新的读请求 aio_handles[i] = sftp_aio_read(file, aio_buffers[i], AIO_BUF_SIZE); if (aio_handles[i] == NULL) { pending--; } } else { pending--; } sftp_aio_free(aio_handles[i]); } } }
4. 其他细节优化
- 确认你链接的libssh是Release版本,开启了O2优化,Debug版本的性能会差2~3倍
- Windows下打开本地文件时添加
O_BINARYflag,避免二进制文件写入时出现不必要的转译开销:fd = open(fullLocalPath, O_CREAT | O_RDWR | O_BINARY, 0777); - 可适当增大读写缓冲区到256KB~1MB,不需要超过4MB,过大会增加内存开销且收益极低
按以上步骤调整后,传输速度基本可以追平WinSCP、pscp等主流工具。
内容的提问来源于stack exchange,提问作者Isaque Neves
相关产品推荐
相关产品推荐

