c++ libssh - ssh_channel_read() 不断返回 0 和 ssh_channel_is_open() returns false

c++ libssh - ssh_channel_read() keeps returning 0 and ssh_channel_is_open() returns false

这是我第一次以编程方式实现 ssh,我很困惑为什么我的代码不起作用——更具体地说,ssh_channel_read()不断返回 0 字节读取。我不知道我做错了什么!我一直在逐步遵循 API 说明,但显然我无意中遗漏了一些东西。

我正在尝试使用用户名 + 密码连接到我的 Pi。这是完整的代码,您可以复制粘贴并编译它:

g++ main.cpp -lssh -o myapp

在代码之后,你可以看到我得到的输出。请不要苛刻,就像我说的,这是我第一次与 SSH 打交道:

#include <iostream>
#include <string>
#include <libssh/libsshpp.hpp>

int main(int argc, const char **argv)
{
   int vbs                    = SSH_LOG_RARE;
   int timeout_ms             = 1000;
   ssh_session session        = ssh_new();

   ssh_channel channel;

   char        buffer[256];
   int         bytes_red;

   if (session == NULL)
   {
      std::cout << "Failed to create ssh session." << std::endl;
      exit(-1);
   }

   ssh_set_blocking(session, 1);

   std::cout << "Created SSH session..." << std::endl;

   ssh_options_set(session, SSH_OPTIONS_HOST, "192.168.1.5");
   ssh_options_set(session, SSH_OPTIONS_PORT_STR, "22");
   ssh_options_set(session, SSH_OPTIONS_USER, "pi@192.168.1.5");
   ssh_options_set(session,SSH_OPTIONS_LOG_VERBOSITY, &vbs);

   int con_result             = ssh_connect(session);
   int auth_result            = ssh_userauth_password(session, "pi", "1234");

   std::cout << "Connecton Result is: "   << con_result  << std::endl;
   std::cout << "Auth Result is: "        << auth_result << std::endl;

   ///////////////////////////////////////////
   // Did we create the session successfully?
   ///////////////////////////////////////////
   if (con_result != SSH_OK)
   {
      std::cout << "SSH connection failed. Error code is:  " << con_result << std::endl;
      ssh_free(session);
      return con_result;
   }

   ///////////////////////////////////////////
   // Did we authenticate?
   ///////////////////////////////////////////
   if (auth_result != SSH_AUTH_SUCCESS)
   {
      std::cout << "SSH authentication failed. Error code is:  " << auth_result << std::endl;
      ssh_free(session);
      return auth_result;
   }

   ///////////////////////////////////////////
   // Create a new ssh_channel
   ///////////////////////////////////////////
   channel = ssh_channel_new(session);

   if (channel == NULL)
   {
      std::cout << "Failed to create SSH channel." << std::endl;
      ssh_free(session);
      return SSH_ERROR;
   }

   if (ssh_channel_is_open(channel))
      std::cout << "Channel is open" << std::endl;
   else
      std::cout << "Channel is closed" << std::endl;

   while(!ssh_channel_is_eof(channel))
   {
      bytes_red = ssh_channel_read_timeout(channel, buffer, sizeof(buffer), 0, timeout_ms);

//    if (bytes_red)
         std::cout << "Bytes read: " << bytes_red << std::endl;
   }

   std::cout << "Exiting ..." << std::endl;

   ssh_channel_close(channel);
   ssh_channel_free(channel);
   ssh_free(session);

  return 0;
}

这是我在 运行 对其进行设置时得到的输出:

$./myapp
Created SSH session...
[2018/05/19 14:57:14.246759, 1] socket_callback_connected:  Socket connection callback: 1 (0)
[2018/05/19 14:57:14.301270, 1] ssh_client_connection_callback:  SSH server banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 14:57:14.301321, 1] ssh_analyze_banner:  Analyzing banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 14:57:14.301337, 1] ssh_analyze_banner:  We are talking to an OpenSSH client version: 7.4 (70400)
Connecton Result is: 0
Auth Result is: 0
Channel is closed
[2018/05/19 14:57:14.669298, 1] ssh_packet_process:  Couldn't do anything with packet type 80
Bytes read: 0
Bytes read: 0
Bytes read: 0
Bytes read: 0
Bytes read: 0
^C
$

我可以看到错误,"Channel is closed"但是为什么?我究竟做错了什么?

在此之后,我也想向服务器发送数据,显然得到反馈。根据我的阅读,ssh_channel_write() 是要使用的函数。

我以前没有以编程方式处理过 SSH,我在写这篇文章的时候正在学习它。

非常感谢您的帮助。

更新

感谢 Jarra,我解决了这个问题!这是有效的最终代码!

#include <iostream>
#include <string>
#include <libssh/libsshpp.hpp>

int main(int argc, const char **argv)
{
   int vbs                    = SSH_LOG_RARE;
   int timeout_ms             = 1000;
   ssh_session session = ssh_new();

   ssh_channel channel;

   char        buffer[256];
   int         bytes_red;

   if (session == NULL)
   {
      std::cout << "Failed to create ssh session." << std::endl;
      exit(-1);
   }

   ssh_set_blocking(session, 1);

   std::cout << "Created SSH session..." << std::endl;

   ssh_options_set(session, SSH_OPTIONS_HOST, "192.168.1.5");
   ssh_options_set(session, SSH_OPTIONS_PORT_STR, "22");
   ssh_options_set(session, SSH_OPTIONS_USER, "pi@192.168.1.5");
   ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &vbs);

   int con_result             = ssh_connect(session);
   int auth_result            = ssh_userauth_password(session, "pi", "1234");

   std::cout << "Connecton Result is: "   << con_result  << std::endl;
   std::cout << "Auth Result is: "        << auth_result << std::endl;

   ///////////////////////////////////////////
   // Did we create the session successfully?
   ///////////////////////////////////////////
   if (con_result != SSH_OK)
   {
      std::cout << "SSH connection failed. Error code is:  " << con_result << std::endl;
      ssh_free(session);
      return con_result;
   }

   ///////////////////////////////////////////
   // Did we authenticate?
   ///////////////////////////////////////////
   if (auth_result != SSH_AUTH_SUCCESS)
   {
      std::cout << "SSH authentication failed. Error code is:  " << auth_result << std::endl;
      ssh_free(session);
      return auth_result;
   }

   ///////////////////////////////////////////
   // Create a new ssh_channel
   ///////////////////////////////////////////
   channel = ssh_channel_new(session);

   if (channel == NULL)
   {
      std::cout << "Failed to create SSH channel." << std::endl;
      ssh_free(session);
      return SSH_ERROR;
   }

   ssh_channel_open_session(channel);

   if (ssh_channel_is_open(channel))
      std::cout << "Channel is open" << std::endl;
   else
      std::cout << "Channel is closed" << std::endl;

   int rc = ssh_channel_request_exec(channel, "ls");


   while(!ssh_channel_is_eof(channel))
   {
      bytes_red = ssh_channel_read_timeout(channel, buffer, sizeof(buffer), 0, timeout_ms);

//    if (bytes_red)
//       std::cout << "Bytes read: " << bytes_red << std::endl;

      std::cout << buffer << std::endl;
   }

   std::cout << "Exiting ..." << std::endl;

   ssh_channel_close(channel);
   ssh_channel_free(channel);
   ssh_free(session);

  return 0;
}

要编译:g++ main.cpp -lssh -o myapp 这是我 运行 时得到的结果:

./myapp
Created SSH session...
[2018/05/19 16:01:41.830861, 1] socket_callback_connected:  Socket connection callback: 1 (0)
[2018/05/19 16:01:41.884875, 1] ssh_client_connection_callback:  SSH server banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 16:01:41.884929, 1] ssh_analyze_banner:  Analyzing banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 16:01:41.884945, 1] ssh_analyze_banner:  We are talking to an OpenSSH client version: 7.4 (70400)
Connecton Result is: 0
Auth Result is: 0
[2018/05/19 16:01:42.258668, 1] ssh_packet_process:  Couldn't do anything with packet type 80
Channel is open
Desktop
Documents
Downloads
Music
Pictures
Public
python_games
Templates
Videos
����s
Exiting ...

我只需要处理最后一点有趣的字符。这是我刚开始使用时直接从我的源代码编辑器中取出来的,所以代码并不完美。

ssh_channel_new 为新频道分配了资源。它打不开。

根据您要实现的目标,您应该在该频道上调用适当的 ssh_channel_open_XXXX 函数。

可以在这里找到一个简单的例子:https://github.com/substack/libssh/blob/c073979235eb0d0587ac9cb3c192e91e32d34b06/examples/exec.c

首先调用ssh_channel_open_session打开会话(shell)通道,然后调用ssh_channel_request_exec执行lsof命令

How/when您将写入频道取决于您打开的频道类型。可以在此处看到写入会话通道的示例(在主机上调用 cat > /dev/null 以将写入的数据传输到 /dev/null 之后):https://github.com/substack/libssh/blob/c073979235eb0d0587ac9cb3c192e91e32d34b06/examples/senddata.c