SSH连接SFTP传输:如何使用libssh库在windows环境下进行(文件、文件夹)传输到远端服务器

avatar
作者
猴君
阅读量:0

由于windows上的编译器一般都是没有libssh库的,所以如何我们想要使用libssh库那么我们将会使用cmake来编译libssh官网给出的源代码

libssh库下载地址:https://www.libssh.org/files/

在这里插入图片描述

配置环境

我们在编译libssh库之前需要先配置一些环境:

  • a) 安装 Visual Studio 或者 MinGW
  • b) 安装OpenSSL http://slproweb.com/products/Win32OpenSSL.htmlC:\Program Files
  • c) 安装zlib http://zlib.net/zlib128-dll.zipC:\Program Files
  • d) 安装CMake http://cmake.org/cmake/resources/software.html

有些库需要将其.dll加入环境变量,具体可自行探索

cmake编译libssh

解压压缩包,进入目录,在当前页面右键打开终端
在这里插入图片描述
执行以下命令:

mkdir build cd build cmake .. 

如果出现一些报错很可能是配置环境的问题,可以观察报错信息逐一解决

打开libssh.sln项目(使用cmake编译的编译器与打开的编译器需一致)
在这里插入图片描述
ssh设为启动项目
在这里插入图片描述
Ctrl + B生成解决项目,生成dlllib文件
在这里插入图片描述

如何使用生成的dll与lib文件

配置lib 方法一

打开vs工程 -》 项目 -》 属性

  1. 将头文件也就是进入include下的路径添加进入附加包含目录
    G:\xxx\libssh-0.10.0\include
    在这里插入图片描述
  2. .lib文件所在目录添加进入附加库目录
    G:\xxx\libssh-0.10.0\build\src\Debug
    在这里插入图片描述
  3. ssh.lib添加进入附加依赖项
    在这里插入图片描述

配置lib 方法二

ssh.lib文件复制到当前项目所在路径下
在这里插入图片描述

ssh.lib导入项目即可,同理头文件也可直接复制进入项目路径
在这里插入图片描述

  • 如果是第一种方法,头文件引入可以#include <libssh/libssh.h>#include <libssh/sftp.h>
  • 如果是第二种方法,头文件引入必须#include "libssh/libssh.h"#include "libssh/sftp.h"

如果编译报错缺少这个文件libssh_version.h
这个文件在这个路径下G:\xxx\libssh-0.10.0\build\include\libssh,可以直接复制到libssh/下使用
在这里插入图片描述

配置dll方法一 将dll配置进入环境变量

点击此电脑 -》右键属性 -》 点击高级系统设置
在这里插入图片描述
在这里插入图片描述
dll文件所在路径添加进入环境变量
G:\xxx\libssh-0.10.0\build\src\Debug
在这里插入图片描述
在这里插入图片描述

配置dll方法二 在编译过后将dll直接与可执行文件.exe文件放在同一目录下

要使得用libssh库的项目能通过编译,需要将头文件以及.lib配置进入项目

如果出现__imp__ xxx类型的链接错误很有很可能是当前项目是X86环境,而libssh库是X64的库,需要将vs执行环境改为X64

传输文件、文件夹代码(适配windows)

int sftp_normal_upload(ssh_session session, sftp_session sftp, const char* local_file_path, const char* remote_file_path) {     sftp_file file = sftp_open(sftp, remote_file_path, O_WRONLY | O_CREAT, 0666);     if (!file) {         fprintf(stderr, "Failed to open remote file: %s:sftp_get_error(%d)\n", remote_file_path, sftp_get_error(sftp));         fprintf(stderr, "Can't create directory: %s\n", ssh_get_error(session));         return -1;     }      FILE* local_file = fopen(local_file_path, "rb");     if (!local_file) {         fprintf(stderr, "Failed to open local file: %s\n", local_file_path);         sftp_close(file);         return -1;     }      // 上传文件内容     char buffer[1024];     size_t bytes_read;     while ((bytes_read = fread(buffer, 1, sizeof(buffer), local_file)) > 0) {         sftp_write(file, buffer, bytes_read);     }      fclose(local_file);     sftp_close(file);     return 1; }    int sftp_recursive_upload(ssh_session session, sftp_session sftp, const char* local_path, const char* remote_path) {      // 计算转换后的宽字符所需缓冲区大小     int bufferSize_local = MultiByteToWideChar(CP_ACP, 0, local_path, -1, NULL, 0);     int bufferSize_remote = MultiByteToWideChar(CP_ACP, 0, remote_path, -1, NULL, 0);      // 分配缓冲区     wchar_t* local_path_to_wchar = (wchar_t*)malloc(bufferSize_local * sizeof(wchar_t));     wchar_t* remote_path_to_wchar = (wchar_t*)malloc(bufferSize_remote * sizeof(wchar_t));     if (local_path_to_wchar == NULL || local_path_to_wchar == NULL) {         fprintf(stderr, "Failed to memory\n");         // 处理内存分配失败的情况         return -1;     }      // 执行转换     MultiByteToWideChar(CP_ACP, 0, local_path, -1, local_path_to_wchar, bufferSize_local);     MultiByteToWideChar(CP_ACP, 0, remote_path, -1, remote_path_to_wchar, bufferSize_remote);      //给local_path追加通配符     const wchar_t* str = L"\\*";     wchar_t local_current[MAX_PATH];      if (wcslen(local_path_to_wchar) + 3 >= MAX_PATH - 1)     {         fprintf(stderr, "Failed to strcat wildcard character\n");         return -1;     }     // 将str1复制到result中     wcscpy(local_current, local_path_to_wchar);     // 追加str2到result中     wcscat(local_current, str);       // 打开本地目录     WIN32_FIND_DATA FindFileData;     HANDLE hFind = INVALID_HANDLE_VALUE;     hFind = FindFirstFile(local_current, &FindFileData);     if (hFind == INVALID_HANDLE_VALUE) {         fprintf(stderr, "Failed to open local directory: %s\n", local_current);         return -1;     }      // 创建服务器目录     sftp_mkdir(sftp, remote_path, 0777);      // 遍历本地目录项     do {         if (wcscmp(FindFileData.cFileName, L".") != 0 && wcscmp(FindFileData.cFileName, L"..") != 0) {             // 构造全路径             wchar_t local_file_path[MAX_PATH];             _snwprintf(local_file_path, sizeof(local_file_path), L"%s\\%s", local_path_to_wchar, FindFileData.cFileName);             wchar_t remote_file_path[MAX_PATH];             _snwprintf(remote_file_path, sizeof(remote_file_path), L"%s/%s", remote_path_to_wchar, FindFileData.cFileName);              // 将宽字符字符串转换为多字节字符字符串             char local_next[MAX_PATH];             char remote_next[MAX_PATH];             if (wcstombs(local_next, local_file_path, sizeof(local_next)) == (size_t)-1 ||                 wcstombs(remote_next, remote_file_path, sizeof(remote_next)) == (size_t)-1) {                 fprintf(stderr, "wchar_t conversion to char failed\n");                 return -1;             }              // 如果本地条目是一个目录,递归上传它             if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {                 sftp_recursive_upload(session, sftp, local_next, remote_next);             }             else { // 如果本地条目是一个普通文件,上传它                 sftp_normal_upload(session, sftp, local_next, remote_next);             }         }     } while (FindNextFile(hFind, &FindFileData) != 0);      free(local_path_to_wchar);     free(remote_path_to_wchar);     FindClose(hFind);     return 1; }   ssh_session ssh_create(const char* target_host, const char* target_username) {     ssh_session session;      // 连接SSH会话     session = ssh_new();     if (!session) {         fprintf(stderr, "Failed to create SSH session\n");         return NULL;     }      ssh_options_set(session, SSH_OPTIONS_HOST, target_host);     ssh_options_set(session, SSH_OPTIONS_USER, target_username);      if (ssh_connect(session) != SSH_OK) {         fprintf(stderr, "Failed to connect to SSH session: %s\n", ssh_get_error(session));         ssh_free(session);         return NULL;     }     return session; }  int sftp_run(ssh_session session, const char* local_file_dir, const char* target_path) {     sftp_session sftp;      // 打开SFTP通道     sftp = sftp_new(session);     if (!sftp) {         fprintf(stderr, "Failed to create SFTP session\n");         ssh_disconnect(session);         ssh_free(session);         return -1;     }      if (sftp_init(sftp) != SSH_OK) {         fprintf(stderr, "Failed to initialize SFTP session\n");         sftp_free(sftp);         ssh_disconnect(session);         ssh_free(session);         return -1;     }       // 得到当前 文件/目录 所在路径     char local_dir[4096];     getcwd(local_dir, sizeof(local_dir));     int len = strlen(local_dir);     if ((len + strlen(local_file_dir) + 2) >= 4095) {         perror("Local filename is too long");         return -1;     }      local_dir[len] = '\\';     local_dir[len + 1] = '\0';     strcat(local_dir, local_file_dir);      struct _stat file_stat;      // 获取文件的详细信息     if (_stat(local_dir, &file_stat) != 0) {         perror("stat");         return -1;     }      // 判断文件类型      //普通文件     if ((file_stat.st_mode & _S_IFMT) == _S_IFREG) {         sftp_normal_upload(session, sftp, local_dir, target_path);     }     //目录文件     else if ((file_stat.st_mode & _S_IFMT) == _S_IFDIR) {         // 递归上传本地目录到远程目录         if (sftp_recursive_upload(session, sftp, local_dir, target_path) != 1) {             fprintf(stderr, "Failed to recursively upload directory\n");             sftp_free(sftp);             ssh_disconnect(session);             ssh_free(session);             return -1;         }     }     else {         printf("%s 既不是普通文件,也不是目录,无法上传\n", local_dir);     }      // 释放     sftp_free(sftp);     ssh_disconnect(session);     ssh_free(session);      return 1; }  int ssh_sftp_transmit_password(const char* target_host, const char* target_username,     const char* target_password, const char* local_file_dir, const char* target_path) {     // ssh连接建立     ssh_session session = ssh_create(target_host, target_username);     if (session == NULL)return -1;      // 身份验证 - 密码     if (ssh_userauth_password(session, NULL, target_password) != SSH_AUTH_SUCCESS) {         fprintf(stderr, "Failed to authenticate with password\n");         ssh_disconnect(session);         ssh_free(session);         return -1;     }      // 传输     int re = sftp_run(session, local_file_dir, target_path);      return re; }   int ssh_sftp_transmit_publickey(const char* target_host, const char* target_username,     const char* local_file_dir, const char* target_path) {     // ssh连接建立     ssh_session session = ssh_create(target_host, target_username);     if (session == NULL)return -1;      // 身份验证 - 密钥     if (ssh_userauth_publickey_auto(session, NULL, NULL) != SSH_AUTH_SUCCESS) {         fprintf(stderr, "Authentication failed: %s\n", ssh_get_error(session));         ssh_disconnect(session);         ssh_free(session);         return -1;     }      // 传输     int re = sftp_run(session, local_file_dir, target_path);      return re; } 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!