libssh2的简单应用

来源:互联网 发布:ntfs for mac激活不了 编辑:程序博客网 时间:2024/05/29 01:52

libssh2的官网:www.libssh2.org;虽然这个网站里面内容是全英文的,我想所有的计算机从事者都能看懂这里面写的内容,这里面提供了很多例子,比如FTP的,shell命令的等等,我在这里介绍一下shell命令的发送和接收返回数据。

example里有个文件名叫exec.c 这个文件是实现shell命令的一个例子:

* Sample showing how to use libssh2 to execute a command remotely.  *  * The sample code has fixed values for host name, user name, password  * and command to run.  *  * Run it like this:  *  * $ ./ssh2_exec 127.0.0.1 user password "uptime"  *  */      #include "libssh2_config.h"  #include <libssh2.h>     #ifdef HAVE_WINSOCK2_H  #include <winsock2.h>  #endif  #ifdef HAVE_SYS_SOCKET_H  #include <sys/socket.h>  #endif  #ifdef HAVE_NETINET_IN_H  #include <netinet/in.h>  #endif  #ifdef HAVE_SYS_SELECT_H  #include <sys/select.h>  #endif  #ifdef HAVE_UNISTD_H  #include <unistd.h>  #endif  #ifdef HAVE_ARPA_INET_H  #include <arpa/inet.h>  #endif     #include <sys/time.h>  #include <sys/types.h>  #include <stdlib.h>  #include <fcntl.h>  #include <errno.h>  #include <stdio.h>  #include <ctype.h>     static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)  {      struct timeval timeout;      int rc;      fd_set fd;      fd_set *writefd = NULL;      fd_set *readfd = NULL;      int dir;         timeout.tv_sec = 10;      timeout.tv_usec = 0;         FD_ZERO(&fd);         FD_SET(socket_fd, &fd);         /* now make sure we wait in the correct direction */       dir = libssh2_session_block_directions(session);           if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)          readfd = &fd;         if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)          writefd = &fd;         rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);         return rc;  }     int main(int argc, char *argv[])  {      const char *hostname = "127.0.0.1";      const char *commandline = "uptime";      const char *username    = "user";      const char *password    = "password";      unsigned long hostaddr;      int sock;      struct sockaddr_in sin;      const char *fingerprint;      LIBSSH2_SESSION *session;      LIBSSH2_CHANNEL *channel;      int rc;      int exitcode;      char *exitsignal=(char *)"none";      int bytecount = 0;      size_t len;      LIBSSH2_KNOWNHOSTS *nh;      int type;     #ifdef WIN32      WSADATA wsadata;      WSAStartup(MAKEWORD(2,0), &wsadata);  #endif      if (argc > 1)          /* must be ip address only */           hostname = argv[1];         if (argc > 2) {          username = argv[2];      }      if (argc > 3) {          password = argv[3];      }      if (argc > 4) {          commandline = argv[4];      }         rc = libssh2_init (0);        if (rc != 0) {          fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);          return 1;      }         hostaddr = inet_addr(hostname);         /* Ultra basic "connect to port 22 on localhost"      * Your code is responsible for creating the socket establishing the      * connection      */       sock = socket(AF_INET, SOCK_STREAM, 0);         sin.sin_family = AF_INET;      sin.sin_port = htons(22);      sin.sin_addr.s_addr = hostaddr;      if (connect(sock, (struct sockaddr*)(&sin),                  sizeof(struct sockaddr_in)) != 0) {          fprintf(stderr, "failed to connect!\n");          return -1;      }         /* Create a session instance */       session = libssh2_session_init();        if (!session)          return -1;         /* tell libssh2 we want it all done non-blocking */       libssh2_session_set_blocking(session, 0);           /* ... start it up. This will trade welcome banners, exchange keys,      * and setup crypto, compression, and MAC layers      */       while ((rc = libssh2_session_handshake(session, sock)) ==               LIBSSH2_ERROR_EAGAIN);      if (rc) {          fprintf(stderr, "Failure establishing SSH session: %d\n", rc);          return -1;      }         nh = libssh2_knownhost_init(session);        if(!nh) {          /* eeek, do cleanup here */           return 2;      }         /* read all hosts from here */       libssh2_knownhost_readfile(nh, "known_hosts",                                   LIBSSH2_KNOWNHOST_FILE_OPENSSH);         /* store all known hosts to here */       libssh2_knownhost_writefile(nh, "dumpfile",                                    LIBSSH2_KNOWNHOST_FILE_OPENSSH);         fingerprint = libssh2_session_hostkey(session, &len, &type);        if(fingerprint) {          struct libssh2_knownhost *host;  #if LIBSSH2_VERSION_NUM >= 0x010206          /* introduced in 1.2.6 */           int check = libssh2_knownhost_checkp(nh, hostname, 22,                                                 fingerprint, len,                                               LIBSSH2_KNOWNHOST_TYPE_PLAIN|                                               LIBSSH2_KNOWNHOST_KEYENC_RAW,                                               &host);  #else          /* 1.2.5 or older */           int check = libssh2_knownhost_check(nh, hostname,                                                fingerprint, len,                                              LIBSSH2_KNOWNHOST_TYPE_PLAIN|                                              LIBSSH2_KNOWNHOST_KEYENC_RAW,                                              &host);  #endif          fprintf(stderr, "Host check: %d, key: %s\n", check,                  (check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?                  host->key:"<none>");             /*****          * At this point, we could verify that 'check' tells us the key is          * fine or bail out.          *****/       }      else {          /* eeek, do cleanup here */           return 3;      }      libssh2_knownhost_free(nh);           if ( strlen(password) != 0 ) {          /* We could authenticate via password */           while ((rc = libssh2_userauth_password(session, username, password)) ==                   LIBSSH2_ERROR_EAGAIN);          if (rc) {              fprintf(stderr, "Authentication by password failed.\n");              goto shutdown;          }      }      else {          /* Or by public key */           while ((rc = libssh2_userauth_publickey_fromfile(session, username,                                                             "/home/user/"                                                           ".ssh/id_rsa.pub",                                                           "/home/user/"                                                           ".ssh/id_rsa",                                                           password)) ==                 LIBSSH2_ERROR_EAGAIN);          if (rc) {              fprintf(stderr, "\tAuthentication by public key failed\n");              goto shutdown;          }      }     #if 0      libssh2_trace(session, ~0 );    #endif         /* Exec non-blocking on the remove host */       while( (channel = libssh2_channel_open_session(session)) == NULL &&               libssh2_session_last_error(session,NULL,NULL,0) ==               LIBSSH2_ERROR_EAGAIN )      {          waitsocket(sock, session);      }      if( channel == NULL )      {          fprintf(stderr,"Error\n");          exit( 1 );      }      while( (rc = libssh2_channel_exec(channel, commandline)) ==               LIBSSH2_ERROR_EAGAIN )      {          waitsocket(sock, session);      }      if( rc != 0 )      {          fprintf(stderr,"Error\n");          exit( 1 );      }      for( ;; )      {          /* loop until we block */           int rc;          do          {              char buffer[0x4000];              rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );                if( rc > 0 )              {                  int i;                  bytecount += rc;                  fprintf(stderr, "We read:\n");                  for( i=0; i < rc; ++i )                      fputc( buffer[i], stderr);                  fprintf(stderr, "\n");              }              else {                  if( rc != LIBSSH2_ERROR_EAGAIN )                      /* no need to output this for the EAGAIN case */                       fprintf(stderr, "libssh2_channel_read returned %d\n", rc);              }          }          while( rc > 0 );             /* this is due to blocking that would occur otherwise so we loop on            this condition */           if( rc == LIBSSH2_ERROR_EAGAIN )          {              waitsocket(sock, session);          }          else              break;      }      exitcode = 127;      while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )            waitsocket(sock, session);         if( rc == 0 )      {          exitcode = libssh2_channel_get_exit_status( channel );            libssh2_channel_get_exit_signal(channel, &exitsignal,                                            NULL, NULL, NULL, NULL, NULL);      }         if (exitsignal)          fprintf(stderr, "\nGot signal: %s\n", exitsignal);      else          fprintf(stderr, "\nEXIT: %d bytecount: %d\n", exitcode, bytecount);         libssh2_channel_free(channel);        channel = NULL;     shutdown:         libssh2_session_disconnect(session,                                   "Normal Shutdown, Thank you for playing");      libssh2_session_free(session);       #ifdef WIN32      closesocket(sock);  #else      close(sock);  #endif      fprintf(stderr, "all done\n");         libssh2_exit();           return 0;  }

做windows连接linux服务器发送shell命令的主要方法有几个简单介绍下:

1.WSAStartup(),打开socket链接库

2.socket(),初始化一个socket套接字

3.connect(),连接到ssh服务器

4.libssh2_session_init(),初始化一个ssh连接

5.libssh2_session_handshake(),将socket和session握手通信

6.libssh2_userauth_password(),验证登陆

7.libssh2_channel_open_session(),打开通道

8.libssh2_channel_exec(),发送shell命令

9.libssh2_channel_read(),读取命令处理结果


这里的8.libssh2_channel_exec(),发送shell命令和心目中想象的不太一样,不能循环发送命令,发送第一次命令时,该命令执行,但是第二次再发送时会返回一个

名字叫LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED的ERROR,也就是说这个函数只能发送一次shell命令就不能再用了,太麻烦了。


在这里这种需求怎么解决:

当调用完libssh2_channel_exec()时,将通道释放掉libssh2_channel_close(),然后再重新打开libssh2_channel_open(),再使用这个libssh2_channel_exec()发送shell命令。

但是在这里可能会出现一个问题,在libssh2_channel_open()的时候并没有把通道打开,调用libssh2_session_last_error()发现这个错误代码是LIBSSH2_ERROR_EAGAIN,在官方网站的解释是这不是一个错误,是一个阻塞的过程,也就是现在这个链接已经阻塞了,需要等等再打开。这也就是最上面那个waitsocket()的作用了。



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 刷信用卡显示不允许降级交易怎么办 每次月经头几天下不来怎么办 邮箱和安全问题都忘记了怎么办 大疆air无人机芯片过热怎么办 脸上反复冒痘痘闭口粉刺怎么办? 手被火烧伤起泡怎么办 手被打火机烧了怎么办 小孩手被火烧了怎么办 手指被火烧伤了怎么办 别人砸坏我家门怎么办 逆水寒经验满了怎么办 tcl魔环显示离线怎么办 城管执法局执法不公平怎么办 人被骗去搞传销怎么办 进了传销想出来怎么办 武汉江夏健康证怎么办 健康证条子掉了怎么办 送外卖的健康证怎么办 美团没有健康证怎么办 健康证不给补办怎么办 南京怎么办健康证去哪里办 浙江横店健康证怎么办 办健康证查乙肝怎么办 餐饮健康证丢了怎么办 办健康证吃了东西怎么办 吃宵夜脸肿了怎么办 晚上不吃宵夜饿了怎么办 办健康证身份证丢了怎么办 宁波二院怎么办健康证 健康证和培训证怎么办 楼下烧煤炉呛人怎么办 衣服染了笔渍怎么办 济宁二院怎么办健康证 刚按揭车的想卖怎么办 房子已过户银行不放贷怎么办 办房贷信用逾期给拒了怎么办 二手房过户了房贷下不来怎么办 没有房证的房子买卖怎么办 老公失踪房产证要他签字怎么办 税务机关对长期欠税怎么办 离婚有贷款的房子怎么办