使用libssh 0.9.5连接SFTP服务器并异步读取文件时遭遇sftp_new: Out of memory错误
我尝试使用libssh 0.9.5连接SFTP服务器并异步读取文件,参考官方示例编写了测试代码,但运行时出现 「Error allocating SFTP session: sftp_new: Out of memory」 错误。不过我可以通过其他软件正常连接reach@reach这个SFTP服务器。
测试代码如下:
//https://api.libssh.org/master/libssh_tutor_sftp.html#sftp_read #include <libssh/libssh.h> #include <libssh/sftp.h> #include <iostream> using namespace std; int main(){ ssh_session sshs = ssh_new(); if(sshs == NULL){ cerr << "Error allocating SSH session: " << ssh_get_error(sshs) << endl; return SSH_ERROR; } ssh_options_set(sshs, SSH_OPTIONS_HOST, "reach"); ssh_options_set(sshs, SSH_OPTIONS_USER, "reach"); //SSH is working fine int rc = ssh_connect(sshs); if(rc != SSH_OK){ cerr << "Error connecting to localhost: " << ssh_get_error(sshs) << endl; return SSH_ERROR; } //Now we talking.... sftp_session sftps = sftp_new(sshs); if(sftps == NULL){ cerr << "Error allocating SFTP session: " << ssh_get_error(sshs) << endl; return SSH_ERROR; } sftp_free(sftps); ssh_disconnect(sshs); ssh_free(sshs); return 0; }
我来帮你分析下这个问题,虽然错误提示是“内存不足”,但通常这种情况不一定是真的系统内存不够,大概率是libssh内部初始化或会话状态的问题。这里有几个你可以尝试的方向:
补全SSH会话的认证步骤:你只调用了
ssh_connect建立了TCP连接,但还没有完成用户认证(比如密码、密钥认证)。SFTP会话的创建依赖于已认证的SSH会话,未认证的情况下调用sftp_new很可能触发内部错误,甚至返回这种误导性的“内存不足”提示。你需要在ssh_connect之后加上认证逻辑,比如密码认证:// 添加密码认证步骤 rc = ssh_userauth_password(sshs, NULL, "你的服务器密码"); if (rc != SSH_OK) { cerr << "Authentication failed: " << ssh_get_error(sshs) << endl; ssh_disconnect(sshs); ssh_free(sshs); return SSH_ERROR; }如果你习惯用密钥认证,也可以使用
ssh_userauth_publickey_auto这类函数完成认证。开启libssh调试日志:默认的错误提示太笼统,开启调试模式能让你看到更详细的内部交互日志,帮你定位真正的问题。在
ssh_new之后添加日志级别设置:int log_level = SSH_LOG_PROTOCOL; ssh_options_set(sshs, SSH_OPTIONS_LOG_VERBOSITY, &log_level);运行程序后会输出SSH协议层面的详细交互信息,能帮你排查是会话状态还是协议交互出了问题。
检查版本兼容性与编译链接:你使用的是libssh 0.9.5,而官方示例是基于master分支的,部分API行为在旧版本可能有差异,建议对照0.9.5的官方文档确认
sftp_new的调用要求。另外也要确保代码编译时正确链接了libssh库、头文件路径配置无误,链接异常也可能导致函数调用返回错误的NULL指针。
另外,你提到其他软件能正常连接,说明服务器端的SFTP服务是正常的,问题基本出在代码流程或libssh的使用方式上,优先补全认证步骤应该能解决大部分这类问题。
内容的提问来源于stack exchange,提问作者Achmad Fathoni

