玉生香 2022-02-22 14:42 采纳率: 0%
浏览 54

libssh2 libssh2_channel_read + libssh2_channel_request_pty 无限阻塞

这段代码去掉libssh2_channel_request_pty 

代码不加libssh2_channel_read  ,libssh2_channel_read  当无数据读时,正常返回0.

代码加上libssh2_channel_request_pty 时,libssh2_channel_read  当无数据读时永久阻塞中,不返回0.一直返回 LIBSSH2_ERROR_EAGAIN

#include <iostream>
#include "CSecureX2.h"
#include "Ctstring.h"
#include "Properties.h"
#include "XFile.h"
#include <winsock2.h>
#include "CLog.h"
#ifdef _DEBUG
#pragma comment( lib, "libssh2d.lib")
#pragma comment( lib, "libcommd.lib")

#else
#pragma comment( lib, "libssh2.lib")
#pragma comment( lib, "libcomm.lib")
#endif
#pragma comment( lib, "ssleay32.lib")
#pragma comment( lib, "Shlwapi.lib")
#pragma comment(lib,"Ws2_32.lib ")

#pragma comment( lib, "libeay32.lib")
#pragma comment( lib, "ssleay32.lib")
#pragma comment( lib, "Crypt32.lib")
/*
* 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.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/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>

#pragma warning(disable:4996)
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 = "192.168.2.121";
	const char *commandline = "uptime\n";
	const char *username = "test";
	const char *password = "test";
	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;
	}


	while ((rc = libssh2_userauth_password(session, username, password)) ==

		LIBSSH2_ERROR_EAGAIN);
	if (rc) {
		fprintf(stderr, "Authentication by password failed.\n");
		goto shutdown;
	}

	/* 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);
	}


	rc = 0;
	while (rc = libssh2_channel_request_pty(channel, "ansi"))
	{
		waitsocket(sock, session);
	}
	if (rc != 0)
	{
		fprintf(stderr, "Error\n");
		exit(1);
	}


	while ((rc = libssh2_channel_shell(channel))
		== LIBSSH2_ERROR_EAGAIN)
	{
		waitsocket(sock, session);
	}

	if (rc != 0)
	{
		fprintf(stderr, "Error\n");
		exit(1);
	}



	while ((rc = libssh2_channel_write(channel, commandline, strlen(commandline))) ==LIBSSH2_ERROR_EAGAIN)
	{
		waitsocket(sock, session);
	}
	if (rc < 0)
	{
		fprintf(stderr, "Error\n");
		exit(1);
	}

	while ((rc = libssh2_channel_send_eof(channel)) == 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;
}
  • 写回答

1条回答 默认 最新

  • 洛阳鱼紫怡 2023-02-07 17:25
    关注

    https://www.libssh2.org/examples/ssh2_exec.html

    没用过这个函数,官网给上有例子可以参考看看

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 2月22日

悬赏问题

  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员
  • ¥15 matlab生成电测深三层曲线模型代码
  • ¥50 随机森林与房贷信用风险模型