视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
libssh2的简单应用
2020-11-09 07:59:01 责编:小采
文档


首先,libssh2.lib的这个库一定要有(下载地址提供:http://download.csdn.net/detail/wyc6668205/5651661) 其次,介绍一下libssh2的官网:www.libssh2.org;虽然这个网站里面内容是全英文的,我想所有的计算机从事者都能看懂这里面写的内容,这里面提供了

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

其次,介绍一下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 
 
#ifdef HAVE_WINSOCK2_H
#include 
#endif
#ifdef HAVE_SYS_SOCKET_H
#include 
#endif
#ifdef HAVE_NETINET_IN_H
#include 
#endif
#ifdef HAVE_SYS_SELECT_H
#include 
#endif
#ifdef HAVE_UNISTD_H
#include 
#endif
#ifdef HAVE_ARPA_INET_H
#include 
#endif
 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
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:"");
 
 /*****
 * 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()的作用了。






下载本文
显示全文
专题