Libssh:ssh_channel_read返回0且ssh_channel_is_open返回false问题求助
嘿,我刚梳理了你遇到的libssh通道问题——虽然你已经搞定了SSH连接和认证,但通道一直没真正打开、读操作返回0的原因其实很明确,咱们一步步拆解问题,再给你修复后的完整读写代码:
问题分析
你遇到的核心问题是:创建ssh_channel后没有发起会话请求。libssh的ssh_channel_new()只是在本地实例化了一个通道对象,必须通过ssh_channel_open_session()与服务器完成通道握手,通道才会真正处于打开状态,才能进行读写操作。
原问题代码
#include <libssh/libssh.h> #include <iostream> #include <string> int main() { ssh_session my_ssh_session = ssh_new(); if (my_ssh_session == nullptr) { std::cerr << "Failed to create SSH session" << std::endl; return 1; } // 设置连接参数 ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "raspberrypi.local"); ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, "pi"); // 连接服务器 int rc = ssh_connect(my_ssh_session); if (rc != SSH_OK) { std::cerr << "Connection failed: " << ssh_get_error(my_ssh_session) << std::endl; ssh_free(my_ssh_session); return 1; } // 密码认证 rc = ssh_userauth_password(my_ssh_session, nullptr, "your_password"); if (rc != SSH_OK) { std::cerr << "Authentication failed: " << ssh_get_error(my_ssh_session) << std::endl; ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); return 1; } std::cout << "Authentication successful!" << std::endl; // 创建通道 ssh_channel channel = ssh_channel_new(my_ssh_session); if (channel == nullptr) { std::cerr << "Failed to create channel" << std::endl; ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); return 1; } // 这里缺少了ssh_channel_open_session()调用! std::cout << "Channel is open? " << (ssh_channel_is_open(channel) ? "Yes" : "No") << std::endl; char buffer[1024]; int nbytes; nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); std::cout << "Bytes read: " << nbytes << std::endl; // 清理资源 ssh_channel_free(channel); ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); return 0; }
编译命令与原运行输出
编译命令
g++ -o ssh_test ssh_test.cpp -lssh
运行输出
Authentication successful! Channel is open? No Bytes read: 0
修复后的可用代码(含完整读写功能)
我已经补上了关键的会话打开步骤,同时实现了向服务器发送命令并读取返回结果的功能:
#include <libssh/libssh.h> #include <iostream> #include <string> #include <cstring> int main() { ssh_session my_ssh_session = ssh_new(); if (my_ssh_session == nullptr) { std::cerr << "Failed to create SSH session" << std::endl; return 1; } // 设置连接参数 ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "raspberrypi.local"); ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, "pi"); // 连接服务器 int rc = ssh_connect(my_ssh_session); if (rc != SSH_OK) { std::cerr << "Connection failed: " << ssh_get_error(my_ssh_session) << std::endl; ssh_free(my_ssh_session); return 1; } // 密码认证 rc = ssh_userauth_password(my_ssh_session, nullptr, "your_password"); if (rc != SSH_OK) { std::cerr << "Authentication failed: " << ssh_get_error(my_ssh_session) << std::endl; ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); return 1; } std::cout << "Authentication successful!" << std::endl; // 创建通道 ssh_channel channel = ssh_channel_new(my_ssh_session); if (channel == nullptr) { std::cerr << "Failed to create channel" << std::endl; ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); return 1; } // 关键步骤:打开会话通道 rc = ssh_channel_open_session(channel); if (rc != SSH_OK) { std::cerr << "Failed to open session channel: " << ssh_get_error(my_ssh_session) << std::endl; ssh_channel_free(channel); ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); return 1; } std::cout << "Channel is open? " << (ssh_channel_is_open(channel) ? "Yes" : "No") << std::endl; // 向服务器发送命令(示例:获取系统信息) std::string command = "uname -a\n"; rc = ssh_channel_write(channel, command.c_str(), command.size()); if (rc < 0) { std::cerr << "Failed to write to channel: " << ssh_get_error(my_ssh_session) << std::endl; ssh_channel_close(channel); ssh_channel_free(channel); ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); return 1; } std::cout << "Sent " << rc << " bytes to server" << std::endl; // 发送EOF标记,告诉服务器没有更多数据要发送 ssh_channel_send_eof(channel); // 循环读取服务器返回的结果 char buffer[1024]; int nbytes; std::cout << "\nServer response:\n"; while ((nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0)) > 0) { std::cout.write(buffer, nbytes); } if (nbytes < 0) { std::cerr << "\nError reading from channel: " << ssh_get_error(my_ssh_session) << std::endl; } // 按顺序清理资源:先关闭通道,再释放会话 ssh_channel_close(channel); ssh_channel_free(channel); ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); return 0; }
核心修复点说明
- 添加
ssh_channel_open_session():这是通道真正激活的关键,必须在创建通道后调用,否则通道只是本地空对象,不会和服务器建立会话连接。 - 完善读写流程:发送命令后调用
ssh_channel_send_eof()告知服务器数据发送完毕,这样服务器才会返回完整的命令输出;同时用循环读取数据,避免遗漏分段返回的内容。 - 规范资源清理:确保通道先关闭再释放,会话先断开再释放,避免内存泄漏或资源残留。
内容的提问来源于stack exchange,提问作者marko
相关产品推荐
相关产品推荐

