当前位置:   article > 正文

libssh2的简单应用

libssh2

首先,libssh2.lib的这个库一定要有(下载地址提供:http://download.csdn.net/detail/wyc6668205/5651661

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

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

  1. /*
  2. * Sample showing how to use libssh2 to execute a command remotely.
  3. *
  4. * The sample code has fixed values for host name, user name, password
  5. * and command to run.
  6. *
  7. * Run it like this:
  8. *
  9. * $ ./ssh2_exec 127.0.0.1 user password "uptime"
  10. *
  11. */
  12. #include "libssh2_config.h"
  13. #include <libssh2.h>
  14. #ifdef HAVE_WINSOCK2_H
  15. #include <winsock2.h>
  16. #endif
  17. #ifdef HAVE_SYS_SOCKET_H
  18. #include <sys/socket.h>
  19. #endif
  20. #ifdef HAVE_NETINET_IN_H
  21. #include <netinet/in.h>
  22. #endif
  23. #ifdef HAVE_SYS_SELECT_H
  24. #include <sys/select.h>
  25. #endif
  26. #ifdef HAVE_UNISTD_H
  27. #include <unistd.h>
  28. #endif
  29. #ifdef HAVE_ARPA_INET_H
  30. #include <arpa/inet.h>
  31. #endif
  32. #include <sys/time.h>
  33. #include <sys/types.h>
  34. #include <stdlib.h>
  35. #include <fcntl.h>
  36. #include <errno.h>
  37. #include <stdio.h>
  38. #include <ctype.h>
  39. static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
  40. {
  41. struct timeval timeout;
  42. int rc;
  43. fd_set fd;
  44. fd_set *writefd = NULL;
  45. fd_set *readfd = NULL;
  46. int dir;
  47. timeout.tv_sec = 10;
  48. timeout.tv_usec = 0;
  49. FD_ZERO(&fd);
  50. FD_SET(socket_fd, &fd);
  51. /* now make sure we wait in the correct direction */
  52. dir = libssh2_session_block_directions(session);
  53. if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
  54. readfd = &fd;
  55. if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
  56. writefd = &fd;
  57. rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
  58. return rc;
  59. }
  60. int main(int argc, char *argv[])
  61. {
  62. const char *hostname = "127.0.0.1";
  63. const char *commandline = "uptime";
  64. const char *username = "user";
  65. const char *password = "password";
  66. unsigned long hostaddr;
  67. int sock;
  68. struct sockaddr_in sin;
  69. const char *fingerprint;
  70. LIBSSH2_SESSION *session;
  71. LIBSSH2_CHANNEL *channel;
  72. int rc;
  73. int exitcode;
  74. char *exitsignal=(char *)"none";
  75. int bytecount = 0;
  76. size_t len;
  77. LIBSSH2_KNOWNHOSTS *nh;
  78. int type;
  79. #ifdef WIN32
  80. WSADATA wsadata;
  81. WSAStartup(MAKEWORD(2,0), &wsadata);
  82. #endif
  83. if (argc > 1)
  84. /* must be ip address only */
  85. hostname = argv[1];
  86. if (argc > 2) {
  87. username = argv[2];
  88. }
  89. if (argc > 3) {
  90. password = argv[3];
  91. }
  92. if (argc > 4) {
  93. commandline = argv[4];
  94. }
  95. rc = libssh2_init (0);
  96. if (rc != 0) {
  97. fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
  98. return 1;
  99. }
  100. hostaddr = inet_addr(hostname);
  101. /* Ultra basic "connect to port 22 on localhost"
  102. * Your code is responsible for creating the socket establishing the
  103. * connection
  104. */
  105. sock = socket(AF_INET, SOCK_STREAM, 0);
  106. sin.sin_family = AF_INET;
  107. sin.sin_port = htons(22);
  108. sin.sin_addr.s_addr = hostaddr;
  109. if (connect(sock, (struct sockaddr*)(&sin),
  110. sizeof(struct sockaddr_in)) != 0) {
  111. fprintf(stderr, "failed to connect!\n");
  112. return -1;
  113. }
  114. /* Create a session instance */
  115. session = libssh2_session_init();
  116. if (!session)
  117. return -1;
  118. /* tell libssh2 we want it all done non-blocking */
  119. libssh2_session_set_blocking(session, 0);
  120. /* ... start it up. This will trade welcome banners, exchange keys,
  121. * and setup crypto, compression, and MAC layers
  122. */
  123. while ((rc = libssh2_session_handshake(session, sock)) ==
  124. LIBSSH2_ERROR_EAGAIN);
  125. if (rc) {
  126. fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
  127. return -1;
  128. }
  129. nh = libssh2_knownhost_init(session);
  130. if(!nh) {
  131. /* eeek, do cleanup here */
  132. return 2;
  133. }
  134. /* read all hosts from here */
  135. libssh2_knownhost_readfile(nh, "known_hosts",
  136. LIBSSH2_KNOWNHOST_FILE_OPENSSH);
  137. /* store all known hosts to here */
  138. libssh2_knownhost_writefile(nh, "dumpfile",
  139. LIBSSH2_KNOWNHOST_FILE_OPENSSH);
  140. fingerprint = libssh2_session_hostkey(session, &len, &type);
  141. if(fingerprint) {
  142. struct libssh2_knownhost *host;
  143. #if LIBSSH2_VERSION_NUM >= 0x010206
  144. /* introduced in 1.2.6 */
  145. int check = libssh2_knownhost_checkp(nh, hostname, 22,
  146. fingerprint, len,
  147. LIBSSH2_KNOWNHOST_TYPE_PLAIN|
  148. LIBSSH2_KNOWNHOST_KEYENC_RAW,
  149. &host);
  150. #else
  151. /* 1.2.5 or older */
  152. int check = libssh2_knownhost_check(nh, hostname,
  153. fingerprint, len,
  154. LIBSSH2_KNOWNHOST_TYPE_PLAIN|
  155. LIBSSH2_KNOWNHOST_KEYENC_RAW,
  156. &host);
  157. #endif
  158. fprintf(stderr, "Host check: %d, key: %s\n", check,
  159. (check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
  160. host->key:"<none>");
  161. /*****
  162. * At this point, we could verify that 'check' tells us the key is
  163. * fine or bail out.
  164. *****/
  165. }
  166. else {
  167. /* eeek, do cleanup here */
  168. return 3;
  169. }
  170. libssh2_knownhost_free(nh);
  171. if ( strlen(password) != 0 ) {
  172. /* We could authenticate via password */
  173. while ((rc = libssh2_userauth_password(session, username, password)) ==
  174. LIBSSH2_ERROR_EAGAIN);
  175. if (rc) {
  176. fprintf(stderr, "Authentication by password failed.\n");
  177. goto shutdown;
  178. }
  179. }
  180. else {
  181. /* Or by public key */
  182. while ((rc = libssh2_userauth_publickey_fromfile(session, username,
  183. "/home/user/"
  184. ".ssh/id_rsa.pub",
  185. "/home/user/"
  186. ".ssh/id_rsa",
  187. password)) ==
  188. LIBSSH2_ERROR_EAGAIN);
  189. if (rc) {
  190. fprintf(stderr, "\tAuthentication by public key failed\n");
  191. goto shutdown;
  192. }
  193. }
  194. #if 0
  195. libssh2_trace(session, ~0 );
  196. #endif
  197. /* Exec non-blocking on the remove host */
  198. while( (channel = libssh2_channel_open_session(session)) == NULL &&
  199. libssh2_session_last_error(session,NULL,NULL,0) ==
  200. LIBSSH2_ERROR_EAGAIN )
  201. {
  202. waitsocket(sock, session);
  203. }
  204. if( channel == NULL )
  205. {
  206. fprintf(stderr,"Error\n");
  207. exit( 1 );
  208. }
  209. while( (rc = libssh2_channel_exec(channel, commandline)) ==
  210. LIBSSH2_ERROR_EAGAIN )
  211. {
  212. waitsocket(sock, session);
  213. }
  214. if( rc != 0 )
  215. {
  216. fprintf(stderr,"Error\n");
  217. exit( 1 );
  218. }
  219. for( ;; )
  220. {
  221. /* loop until we block */
  222. int rc;
  223. do
  224. {
  225. char buffer[0x4000];
  226. rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
  227. if( rc > 0 )
  228. {
  229. int i;
  230. bytecount += rc;
  231. fprintf(stderr, "We read:\n");
  232. for( i=0; i < rc; ++i )
  233. fputc( buffer[i], stderr);
  234. fprintf(stderr, "\n");
  235. }
  236. else {
  237. if( rc != LIBSSH2_ERROR_EAGAIN )
  238. /* no need to output this for the EAGAIN case */
  239. fprintf(stderr, "libssh2_channel_read returned %d\n", rc);
  240. }
  241. }
  242. while( rc > 0 );
  243. /* this is due to blocking that would occur otherwise so we loop on
  244. this condition */
  245. if( rc == LIBSSH2_ERROR_EAGAIN )
  246. {
  247. waitsocket(sock, session);
  248. }
  249. else
  250. break;
  251. }
  252. exitcode = 127;
  253. while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )
  254. waitsocket(sock, session);
  255. if( rc == 0 )
  256. {
  257. exitcode = libssh2_channel_get_exit_status( channel );
  258. libssh2_channel_get_exit_signal(channel, &exitsignal,
  259. NULL, NULL, NULL, NULL, NULL);
  260. }
  261. if (exitsignal)
  262. fprintf(stderr, "\nGot signal: %s\n", exitsignal);
  263. else
  264. fprintf(stderr, "\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
  265. libssh2_channel_free(channel);
  266. channel = NULL;
  267. shutdown:
  268. libssh2_session_disconnect(session,
  269. "Normal Shutdown, Thank you for playing");
  270. libssh2_session_free(session);
  271. #ifdef WIN32
  272. closesocket(sock);
  273. #else
  274. close(sock);
  275. #endif
  276. fprintf(stderr, "all done\n");
  277. libssh2_exit();
  278. return 0;
  279. }
做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()的作用了。







声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/960832
推荐阅读
相关标签
  

闽ICP备14008679号