当前位置:   article > 正文

libssh2编译lib/dll与使用的步骤_libssh2.dll

libssh2.dll

1:下载源码:libssh2https://www.libssh2.org/

 

 2.OpenSSL安装

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

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

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

这里仅仅是使用安装目录的库文件。

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

  1. mkdir build
  2. cd build
  3. cmake ..

如果环境正确:

  1. -- Configuring done
  2. -- Generating done
  3. -- 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的ALL_Build.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})

重新编译: 

  1.    目录: E:\libssh2-libssh2-1.10.0\build\src\Release
  2. Mode                 LastWriteTime         Length Name
  3. ----                 -------------         ------ ----
  4. -a----         2021/9/26     10:29         226304 libssh2.dll
  5. -a----         2021/9/26     10:29          19538 libssh2.exp
  6. -a----         2021/9/26     10:29          32788 libssh2.lib

这样就可以正常使用dll.

但是如果想要二次封装为自己的dll的话,就需要还原原来的add_library(libssh2 ${SOURCES}),来使用libssh2.lib进行使用。

二次封装

这里想要将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:

  1. #include "libssh2_config.h"
  2. #include "libssh2.h"
  3. #include "libssh2_sftp.h"
  4. #ifdef HAVE_WINSOCK2_H
  5. # include <winsock2.h>
  6. #endif
  7. #ifdef HAVE_SYS_SOCKET_H
  8. # include <sys/socket.h>
  9. #endif
  10. #ifdef HAVE_NETINET_IN_H
  11. # include <netinet/in.h>
  12. #endif
  13. # ifdef HAVE_UNISTD_H
  14. #include <unistd.h>
  15. #endif
  16. #ifdef HAVE_ARPA_INET_H
  17. # include <arpa/inet.h>
  18. #endif
  19. #ifdef HAVE_SYS_TIME_H
  20. # include <sys/time.h>
  21. #endif
  22. #include <sys/types.h>
  23. #include <fcntl.h>
  24. #include <errno.h>
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. const char* username = "username";
  28. const char* password = "password";
  29. unsigned long hostaddr = 0;//inet_addr("192.168.3.1"); init in anyfunction
  30. unsigned long getIP() {
  31. if (!hostaddr)
  32. {
  33. return inet_addr("192.168.3.1");
  34. }
  35. return hostaddr;
  36. }
  37. int sftp_download(char* loclfile, char* sftppath)
  38. {
  39. unsigned long hostaddr = getIP();
  40. int sock, i, auth_pw = 1;
  41. struct sockaddr_in sin;
  42. const char* fingerprint;
  43. LIBSSH2_SESSION* session;
  44. int rc;
  45. FILE* local;
  46. LIBSSH2_SFTP* sftp_session;
  47. LIBSSH2_SFTP_HANDLE* sftp_handle;
  48. LIBSSH2_SFTP_ATTRIBUTES attrs;
  49. char mem[1024 * 100];
  50. size_t nread;
  51. char* ptr;
  52. #ifdef WIN32
  53. WSADATA wsadata;
  54. int err;
  55. err = WSAStartup(MAKEWORD(2, 0), &wsadata);
  56. if (err) {
  57. fprintf(stderr, "WSAStartup failed with error: %d\n", err);
  58. return -1;
  59. }
  60. #endif
  61. rc = libssh2_init(0);
  62. if (rc) {
  63. fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
  64. return -1;
  65. }
  66. local = fopen(loclfile, "rb");
  67. if (!local) {
  68. fprintf(stderr, "Can't open local file %s\n", loclfile);
  69. return -1;
  70. }
  71. /*
  72. * The application code is responsible for creating the socket
  73. * and establishing the connection
  74. */
  75. sock = socket(AF_INET, SOCK_STREAM, 0);
  76. sin.sin_family = AF_INET;
  77. sin.sin_port = htons(22);
  78. sin.sin_addr.s_addr = hostaddr;
  79. if (connect(sock, (struct sockaddr*)(&sin),
  80. sizeof(struct sockaddr_in)) != 0) {
  81. fprintf(stderr, "failed to connect!\n");
  82. return -1;
  83. }
  84. /* Create a session instance
  85. */
  86. session = libssh2_session_init();
  87. if (!session)
  88. return -1;
  89. /* Since we have set non-blocking, tell libssh2 we are blocking */
  90. libssh2_session_set_blocking(session, 1);
  91. /* ... start it up. This will trade welcome banners, exchange keys,
  92. * and setup crypto, compression, and MAC layers
  93. */
  94. rc = libssh2_session_handshake(session, sock);
  95. if (rc) {
  96. fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
  97. return -1;
  98. }
  99. if (auth_pw) {
  100. /* We could authenticate via password */
  101. if (libssh2_userauth_password(session, username, password)) {
  102. fprintf(stderr, "Authentication by password failed.\n");
  103. goto shutdown;
  104. }
  105. }
  106. sftp_session = libssh2_sftp_init(session);
  107. if (!sftp_session) {
  108. fprintf(stderr, "Unable to init SFTP session\n");
  109. goto shutdown;
  110. }
  111. /* Request a file via SFTP */
  112. sftp_handle =
  113. libssh2_sftp_open(sftp_session, sftppath,
  114. LIBSSH2_FXF_CREAT | LIBSSH2_FXF_WRITE | LIBSSH2_FXF_READ,
  115. LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR |
  116. LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IROTH);
  117. if (!sftp_handle) {
  118. fprintf(stderr, "Unable to open file with SFTP\n");
  119. goto shutdown;
  120. }
  121. if (libssh2_sftp_fstat_ex(sftp_handle, &attrs, 0) < 0) {
  122. fprintf(stderr, "libssh2_sftp_fstat_ex failed\n");
  123. goto shutdown;
  124. }
  125. else
  126. libssh2_sftp_seek64(sftp_handle, attrs.filesize);
  127. if (!sftp_handle) {
  128. fprintf(stderr, "Unable to open file with SFTP\n");
  129. goto shutdown;
  130. }
  131. //fprintf(stderr, "libssh2_sftp_open() is done, now send data!\n");
  132. do {
  133. nread = fread(mem, 1, sizeof(mem), local);
  134. if (nread <= 0) {
  135. /* end of file */
  136. break;
  137. }
  138. ptr = mem;
  139. do {
  140. /* write data in a loop until we block */
  141. rc = libssh2_sftp_write(sftp_handle, ptr, nread);
  142. if (rc < 0)
  143. break;
  144. ptr += rc;
  145. nread -= rc;
  146. } while (nread);
  147. } while (rc > 0);
  148. libssh2_sftp_close(sftp_handle);
  149. libssh2_sftp_shutdown(sftp_session);
  150. shutdown:
  151. libssh2_session_disconnect(session,
  152. "Normal Shutdown, Thank you for playing");
  153. libssh2_session_free(session);
  154. #ifdef WIN32
  155. closesocket(sock);
  156. #else
  157. close(sock);
  158. #endif
  159. if (local)
  160. fclose(local);
  161. libssh2_exit();
  162. return 0;
  163. }
  164. static int waitsocket(int socket_fd, LIBSSH2_SESSION* session)
  165. {
  166. struct timeval timeout;
  167. int rc;
  168. fd_set fd;
  169. fd_set* writefd = NULL;
  170. fd_set* readfd = NULL;
  171. int dir;
  172. timeout.tv_sec = 10;
  173. timeout.tv_usec = 0;
  174. FD_ZERO(&fd);
  175. FD_SET(socket_fd, &fd);
  176. /* now make sure we wait in the correct direction */
  177. dir = libssh2_session_block_directions(session);
  178. if (dir & LIBSSH2_SESSION_BLOCK_INBOUND)
  179. readfd = &fd;
  180. if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
  181. writefd = &fd;
  182. rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
  183. return rc;
  184. }
  185. int ssh_exec(char* commandline)
  186. {
  187. unsigned long hostaddr = getIP();
  188. int sock;
  189. struct sockaddr_in sin;
  190. const char* fingerprint;
  191. LIBSSH2_SESSION* session;
  192. LIBSSH2_CHANNEL* channel;
  193. int rc;
  194. int exitcode;
  195. char* exitsignal = (char*)"none";
  196. int bytecount = 0;
  197. size_t len;
  198. LIBSSH2_KNOWNHOSTS* nh;
  199. int type;
  200. #ifdef WIN32
  201. WSADATA wsadata;
  202. int err;
  203. err = WSAStartup(MAKEWORD(2, 0), &wsadata);
  204. if (err != 0) {
  205. fprintf(stderr, "WSAStartup failed with error: %d\n", err);
  206. return -1;
  207. }
  208. #endif
  209. rc = libssh2_init(0);
  210. if (rc != 0) {
  211. fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
  212. return -1;
  213. }
  214. /* Ultra basic "connect to port 22 on localhost"
  215. * Your code is responsible for creating the socket establishing the
  216. * connection
  217. */
  218. sock = socket(AF_INET, SOCK_STREAM, 0);
  219. sin.sin_family = AF_INET;
  220. sin.sin_port = htons(22);
  221. sin.sin_addr.s_addr = hostaddr;
  222. if (connect(sock, (struct sockaddr*)(&sin),
  223. sizeof(struct sockaddr_in)) != 0) {
  224. fprintf(stderr, "failed to connect!\n");
  225. return -1;
  226. }
  227. /* Create a session instance */
  228. session = libssh2_session_init();
  229. if (!session)
  230. return -1;
  231. /* tell libssh2 we want it all done non-blocking */
  232. libssh2_session_set_blocking(session, 0);
  233. /* ... start it up. This will trade welcome banners, exchange keys,
  234. * and setup crypto, compression, and MAC layers
  235. */
  236. while ((rc = libssh2_session_handshake(session, sock)) ==
  237. LIBSSH2_ERROR_EAGAIN);
  238. if (rc) {
  239. fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
  240. return -1;
  241. }
  242. nh = libssh2_knownhost_init(session);
  243. if (!nh) {
  244. /* eeek, do cleanup here */
  245. return -2;
  246. }
  247. /* read all hosts from here */
  248. libssh2_knownhost_readfile(nh, "known_hosts",
  249. LIBSSH2_KNOWNHOST_FILE_OPENSSH);
  250. /* store all known hosts to here */
  251. libssh2_knownhost_writefile(nh, "dumpfile",
  252. LIBSSH2_KNOWNHOST_FILE_OPENSSH);
  253. libssh2_knownhost_free(nh);
  254. if (1) {
  255. /* We could authenticate via password */
  256. while ((rc = libssh2_userauth_password(session, username, password)) ==
  257. LIBSSH2_ERROR_EAGAIN);
  258. if (rc) {
  259. fprintf(stderr, "Authentication by password failed.\n");
  260. goto shutdown;
  261. }
  262. }
  263. #if 0
  264. libssh2_trace(session, ~0);
  265. #endif
  266. /* Exec non-blocking on the remove host */
  267. while ((channel = libssh2_channel_open_session(session)) == NULL &&
  268. libssh2_session_last_error(session, NULL, NULL, 0) ==
  269. LIBSSH2_ERROR_EAGAIN) {
  270. waitsocket(sock, session);
  271. }
  272. if (channel == NULL) {
  273. fprintf(stderr, "Error\n");
  274. exit(1);
  275. }
  276. while ((rc = libssh2_channel_exec(channel, commandline)) ==
  277. LIBSSH2_ERROR_EAGAIN) {
  278. waitsocket(sock, session);
  279. }
  280. if (rc != 0) {
  281. fprintf(stderr, "Error\n");
  282. exit(1);
  283. }
  284. for (;;) {
  285. /* loop until we block */
  286. int rc;
  287. do {
  288. char buffer[0x4000];
  289. rc = libssh2_channel_read(channel, buffer, sizeof(buffer));
  290. if (rc > 0) {
  291. int i;
  292. bytecount += rc;
  293. fprintf(stderr, "We read:\n");
  294. for (i = 0; i < rc; ++i)
  295. fputc(buffer[i], stderr);
  296. fprintf(stderr, "\n");
  297. }
  298. else {
  299. if (rc != LIBSSH2_ERROR_EAGAIN)
  300. /* no need to output this for the EAGAIN case */
  301. fprintf(stderr, "returned %d\n", rc);
  302. }
  303. } while (rc > 0);
  304. /* this is due to blocking that would occur otherwise so we loop on
  305. this condition */
  306. if (rc == LIBSSH2_ERROR_EAGAIN) {
  307. waitsocket(sock, session);
  308. }
  309. else
  310. break;
  311. }
  312. exitcode = 127;
  313. while ((rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN)
  314. waitsocket(sock, session);
  315. if (rc == 0) {
  316. exitcode = libssh2_channel_get_exit_status(channel);
  317. libssh2_channel_get_exit_signal(channel, &exitsignal,
  318. NULL, NULL, NULL, NULL, NULL);
  319. }
  320. if (exitsignal)
  321. fprintf(stderr, "\nGot signal: %s\n", exitsignal);
  322. else
  323. fprintf(stderr, "\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
  324. libssh2_channel_free(channel);
  325. channel = NULL;
  326. shutdown:
  327. libssh2_session_disconnect(session,
  328. "Normal Shutdown, Thank you for playing");
  329. libssh2_session_free(session);
  330. #ifdef WIN32
  331. closesocket(sock);
  332. #else
  333. close(sock);
  334. #endif
  335. libssh2_exit();
  336. return 0;
  337. }
  338. __declspec(dllexport) download_file(char* loclfile)
  339. {
  340. char sftppath[512] = "/home/XXX/";
  341. strcat(sftppath, loclfile);
  342. return sftp_download(loclfile, sftppath);
  343. }
  344. __declspec(dllexport) int setip(char* IP)
  345. {
  346. hostaddr = inet_addr(IP);
  347. return 0;
  348. }
  349. __declspec(dllexport) int my_exec(char *cmd)
  350. {
  351. ssh_exec(cmd);
  352. return 0;
  353. }

编译命令:

Clang main.c -lexample-ssh2_exec

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

改进1:

Dll無法直接改名!

將文件名改为需要的如XXX.c,然后替换Cmakelists.txt:

  1. include(CheckIncludeFiles)
  2. include(CheckSymbolExists)
  3. include(CopyRuntimeDependencies)
  4. include(SocketLibraries)
  5. append_needed_socket_libraries(LIBRARIES)
  6. add_library(XXX SHARED XXX.c)
  7. list(APPEND EXAMPLE_TARGETS XXX)
  8. # to find generated header
  9. target_include_directories(XXX PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
  10. target_link_libraries(XXX libssh2 ${LIBRARIES})
  11. add_target_to_copy_dependencies(
  12. TARGET copy_example_dependencies
  13. DEPENDENCIES ${RUNTIME_DEPENDENCIES}
  14. BEFORE_TARGETS ${EXAMPLE_TARGETS})

将其中的XXX 改为自己的文件名即可,就会在libssh2-libssh2-1.10.0\build\example\Release生成对应的dll

改进2:

提供用户包含libcrypto-3-x64.dll文件,显得不专业。

在VS添加指定的lib进行重新编译: 

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

闽ICP备14008679号