IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> libssh2编译lib/dll与使用的步骤 -> 正文阅读

[C++知识库]libssh2编译lib/dll与使用的步骤

1:下载源码:libssh2icon-default.png?t=L892https://www.libssh2.org/

?

?2.OpenSSL安装

编译libssh2需要安装OpenSSL,这里自己编译库比较复杂,直接安装带库的包比较方便:

直接从?Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions?下载

注意,不要下载 light 版本,因为 light 版本不带库文件。

3.在根目录创建编译目录

mkdir build
cd build
cmake ..

如果环境正确:

-- Configuring done
-- Generating done
-- Build files have been written to: E:/libssh2-libssh2-1.10.0/build

执行:

cmake --build .

将会在E:\libssh2-libssh2-1.10.0\build\example\Debug中编译出各个例子的exe文件。

同样在E:\libssh2-libssh2-1.10.0\build\src\Debug中会生成libssh2.lib文件。

4.编译dll

双击上一级E:\libssh2-libssh2-1.10.0\build\example的example-ssh2.vcxproj(任何一个都行)

打开VS:

这里我将Debug模式改为了release,重新生成libssh2目录:

在E:\libssh2-libssh2-1.10.0\build\src\Release便生成新的release的lib.

修改libssh2文件夹下的CmakeLists.txt文件:

add_library(libssh2 ${SOURCES})

?改为:

add_library(libssh2 SHARED ${SOURCES})

重新编译:?

???目录: E:\libssh2-libssh2-1.10.0\build\src\Release

Mode ????????????????LastWriteTime ????????Length Name

---- ????????????????------------- ????????------ ----

-a---- ????????2021/9/26 ????10:29 ????????226304 libssh2.dll

-a---- ????????2021/9/26 ????10:29 ?????????19538 libssh2.exp

-a---- ????????2021/9/26 ????10:29 ?????????32788 libssh2.lib

这样就可以正常使用dll.

使用

这里想要将libssh2的功能二次封装为dll,提供简洁的调用。

为了减少工作量:

随便选取一个例子,如example-ssh2_exec,将包含的CMakeLists.txt的:

add_executable(example-${example} ${example}.c)

改为:

add_library(example-${example}?SHARED ${example}.c)

然后修改其中的Source File文件ssh2_exec.c:

#include "libssh2_config.h"
#include "libssh2.h"
#include "libssh2_sftp.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_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif

#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>

const char* username = "username";
const char* password = "password";
unsigned long hostaddr = 0;//inet_addr("192.168.3.1"); init in anyfunction

unsigned long getIP() {
    if (!hostaddr)
    {
        return inet_addr("192.168.3.1");
    }
    return hostaddr;
}

int sftp_download(char* loclfile, char* sftppath)
{
    unsigned long hostaddr = getIP();
    int sock, i, auth_pw = 1;
    struct sockaddr_in sin;
    const char* fingerprint;
    LIBSSH2_SESSION* session;
    int rc;
    FILE* local;
    LIBSSH2_SFTP* sftp_session;
    LIBSSH2_SFTP_HANDLE* sftp_handle;
    LIBSSH2_SFTP_ATTRIBUTES attrs;
    char mem[1024 * 100];
    size_t nread;
    char* ptr;

#ifdef WIN32
    WSADATA wsadata;
    int err;

    err = WSAStartup(MAKEWORD(2, 0), &wsadata);
    if (err) {
        fprintf(stderr, "WSAStartup failed with error: %d\n", err);
        return -1;
    }
#endif

    rc = libssh2_init(0);
    if (rc) {
        fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
        return -1;
    }

    local = fopen(loclfile, "rb");
    if (!local) {
        fprintf(stderr, "Can't open local file %s\n", loclfile);
        return -1;
    }

    /*
     * The application code is responsible for creating the socket
     * and 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;

    /* Since we have set non-blocking, tell libssh2 we are blocking */
    libssh2_session_set_blocking(session, 1);

    /* ... start it up. This will trade welcome banners, exchange keys,
     * and setup crypto, compression, and MAC layers
     */
    rc = libssh2_session_handshake(session, sock);
    if (rc) {
        fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
        return -1;
    }

    if (auth_pw) {
        /* We could authenticate via password */
        if (libssh2_userauth_password(session, username, password)) {
            fprintf(stderr, "Authentication by password failed.\n");
            goto shutdown;
        }
    }

    sftp_session = libssh2_sftp_init(session);

    if (!sftp_session) {
        fprintf(stderr, "Unable to init SFTP session\n");
        goto shutdown;
    }

    /* Request a file via SFTP */

    sftp_handle =
        libssh2_sftp_open(sftp_session, sftppath,
            LIBSSH2_FXF_CREAT | LIBSSH2_FXF_WRITE | LIBSSH2_FXF_READ,
            LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR |
            LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IROTH);
    if (!sftp_handle) {
        fprintf(stderr, "Unable to open file with SFTP\n");
        goto shutdown;
    }

    if (libssh2_sftp_fstat_ex(sftp_handle, &attrs, 0) < 0) {
        fprintf(stderr, "libssh2_sftp_fstat_ex failed\n");
        goto shutdown;
    }
    else
        libssh2_sftp_seek64(sftp_handle, attrs.filesize);

    if (!sftp_handle) {
        fprintf(stderr, "Unable to open file with SFTP\n");
        goto shutdown;
    }
    //fprintf(stderr, "libssh2_sftp_open() is done, now send data!\n");
    do {
        nread = fread(mem, 1, sizeof(mem), local);
        if (nread <= 0) {
            /* end of file */
            break;
        }
        ptr = mem;

        do {
            /* write data in a loop until we block */
            rc = libssh2_sftp_write(sftp_handle, ptr, nread);
            if (rc < 0)
                break;
            ptr += rc;
            nread -= rc;
        } while (nread);

    } while (rc > 0);

    libssh2_sftp_close(sftp_handle);
    libssh2_sftp_shutdown(sftp_session);

shutdown:
    libssh2_session_disconnect(session,
        "Normal Shutdown, Thank you for playing");
    libssh2_session_free(session);

#ifdef WIN32
    closesocket(sock);
#else
    close(sock);
#endif
    if (local)
        fclose(local);
    libssh2_exit();

    return 0;
}

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 ssh_exec(char* commandline)
{
    unsigned long hostaddr = getIP();
    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;
    int err;

    err = WSAStartup(MAKEWORD(2, 0), &wsadata);
    if (err != 0) {
        fprintf(stderr, "WSAStartup failed with error: %d\n", err);
        return -1;
    }
#endif

    rc = libssh2_init(0);
    if (rc != 0) {
        fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
        return -1;
    }

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

    libssh2_knownhost_free(nh);

    if (1) {
        /* 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;
        }
    }

#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, "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

    libssh2_exit();

    return 0;
}


__declspec(dllexport) download_file(char* loclfile)
{
    char sftppath[512] = "/home/XXX/";
    strcat(sftppath, loclfile);
    return sftp_download(loclfile, sftppath);
}

__declspec(dllexport) int setip(char* IP)
{
    hostaddr = inet_addr(IP);
    return 0;
}

__declspec(dllexport) int my_exec(char *cmd)
{
    ssh_exec(cmd);
    return 0;
}

编译命令:

Clang main.c -lexample-ssh2_exec

注意在其他电脑中不仅需要拷贝本次编译的dll,在安装OpenSSL时的安装目录下的bin文件中包含其他的可能需要的dll,需要拷贝过来,如libcrypto-3-x64.dll。

注意:

Dll無法直接改名:

將其中一部分改爲,清理並重新生成才能單獨編譯該文件:

include(CheckIncludeFiles)
include(CheckSymbolExists)
include(CopyRuntimeDependencies)
include(SocketLibraries)

append_needed_socket_libraries(LIBRARIES)


add_library(XXX SHARED XXX.c)
list(APPEND EXAMPLE_TARGETS XXX)
# to find generated header
target_include_directories(XXXPRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(XXX libssh2 ${LIBRARIES})

add_target_to_copy_dependencies(
  TARGET copy_example_dependencies
  DEPENDENCIES ${RUNTIME_DEPENDENCIES}
  BEFORE_TARGETS ${EXAMPLE_TARGETS})

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-27 13:54:18  更:2021-09-27 13:56:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:03:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码