sftp通信攻关——qt环境下使用c++实现

最近涉及到sftp通信编码。上传测试代码记录一下。

  头文件:

 
  1. #ifndef SFTPMANAGER_H

  2. #define SFTPMANAGER_H

  3.  
  4. #ifdef WIN32

  5. #include "libssh2/win32/libssh2_config.h"

  6. #endif

  7. #include <mutex>

  8. #include <memory>

  9. #include <QThread>

  10. #include <iostream>

  11. #include <vector>

  12. #include <libssh2/libssh2.h>

  13. #ifdef WIN32

  14. #include <windows.h>

  15. #include <winsock2.h>

  16. #pragma comment(lib, "Ws2_32.lib")

  17. #else

  18. #include <sys/socket.h>

  19. #include <unistd.h>

  20. #include <arpa/inet.h>

  21. #endif

  22.  
  23.  
  24.  
  25. class SftpManager

  26. {

  27. public:

  28.  
  29. SftpManager();

  30. virtual ~SftpManager();

  31.  
  32. bool connect(std::string szIp, int nPort = 22);

  33.  
  34. bool createSession();

  35.  
  36. bool login(std::string szUserName, std::string szPassword);

  37.  
  38. bool read();

  39.  
  40. bool mkdir();

  41.  
  42. bool readAndWrite();

  43.  
  44. private:

  45. SOCKET m_socket;

  46. LIBSSH2_SESSION *m_session = nullptr;

  47.  
  48. std::vector<LIBSSH2_CHANNEL*> m_channels;

  49. //std::vector<std::mutex *> m_channel_mutexs;

  50. std::vector<std::shared_ptr<std::mutex>> m_channel_mutexs;

  51. static std::string m_ipAddress;

  52. static int m_port;

  53. static std::string m_username;

  54. static std::string m_password;

  55.  
  56. static void initConnectionInfo();

  57. static int waitsocket(int socket_fd, LIBSSH2_SESSION *session);

  58. void shutDown();

  59. static std::string ipAddress();

  60. static std::string username();

  61. static std::string password();

  62. static int port();

  63. };

  64.  
  65. #endif // SFTPMANAGER_H

源文件:

 
  1. #include "SftpManager.h"

  2. #include <QtXml>

  3. #include <libssh2/libssh2_sftp.h>

  4. #define STORAGE "d:\\src\\test.txt"

  5.  
  6. std::string SftpManager::m_password;

  7. std::string SftpManager::m_username;

  8. std::string SftpManager::m_ipAddress;

  9. int SftpManager::m_port;

  10. const char *sftppath = "/home/loohos-01/abc/test";

  11. const char *m_sftppath = "/home/loohos-01/abc/test_mkdir";

  12. const char *m_dest = "/home/loohos-01/abc/test_dest";

  13.  
  14.  
  15.  
  16.  
  17. SftpManager::SftpManager()

  18. {

  19.  
  20. }

  21. SftpManager::~SftpManager()

  22. {

  23. if (!m_channels.empty()){

  24. for (auto channel : m_channels) if (nullptr != channel) libssh2_channel_free(channel);

  25. m_channels.clear();

  26. }

  27. /*

  28. if (!m_channel_mutexs.empty()){

  29. for (auto mtx : m_channel_mutexs) delete mtx;

  30. m_channel_mutexs.clear();

  31. }

  32. */

  33.  
  34. if (nullptr != m_session){

  35. libssh2_session_disconnect(m_session, "Bye bye, Thank you");

  36. libssh2_session_free(m_session);

  37. m_session = nullptr;

  38. }

  39.  
  40. libssh2_exit();

  41.  
  42. if (INVALID_SOCKET != m_socket) closesocket(m_socket);

  43.  
  44. #ifdef WIN32

  45. WSACleanup();

  46. #endif

  47.  
  48. }

  49.  
  50. int SftpManager::waitsocket(int socket_fd, LIBSSH2_SESSION *session )

  51. {

  52. struct timeval timeout;

  53. int rc;

  54. fd_set fd;

  55. fd_set *writefd = NULL;

  56. fd_set *readfd = NULL;

  57. int dir;

  58.  
  59. timeout.tv_sec = 10;

  60. timeout.tv_usec = 0;

  61.  
  62. FD_ZERO(&fd);

  63. FD_SET(socket_fd, &fd);

  64.  
  65. dir = libssh2_session_block_directions(session);

  66.  
  67. if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)

  68. readfd = &fd;

  69.  
  70. if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)

  71. writefd = &fd;

  72.  
  73. rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);

  74.  
  75. return rc;

  76. }

  77.  
  78. bool SftpManager::connect(std::string szIp, int nPort)

  79. {

  80. unsigned long hostaddr;

  81. int sock, i, auth_pw = 1;

  82. struct sockaddr_in sin;

  83. const char *fingerprint;

  84. LIBSSH2_SESSION *session;

  85. const char *username = "loohos-01";

  86. const char *password = "liuhe1688";

  87.  
  88.  
  89. #ifdef HAVE_GETTIMEOFDAY

  90. struct timeval start;

  91. struct timeval end;

  92. long time_ms;

  93. #endif

  94. int rc;

  95. int total = 0;

  96. int spin = 0;

  97. LIBSSH2_SFTP *sftp_session;

  98. LIBSSH2_SFTP_HANDLE *sftp_handle;

  99.  
  100. #ifdef WIN32

  101. WSADATA wsadata;

  102. int err;

  103.  
  104. err = WSAStartup(MAKEWORD(2,0), &wsadata);

  105. if(err != 0)

  106. {

  107. qDebug() << "WSAStartup failed with error:" << err;

  108. return false;

  109. }

  110. #endif

  111. if(szIp == ""){

  112. szIp = ipAddress();

  113. }

  114. if(nPort < 1){

  115. nPort = port();

  116. }

  117. rc = libssh2_init(0);

  118. if(rc != 0){

  119. qDebug() << "libssh2 initialization failed." << rc;

  120. return false;

  121. }

  122. hostaddr = inet_addr(szIp.c_str());

  123. m_socket = socket(AF_INET, SOCK_STREAM, 0);

  124.  
  125. sin.sin_family = AF_INET;

  126. sin.sin_port = htons(22);

  127. sin.sin_addr.s_addr = hostaddr;

  128. rc = ::connect(m_socket, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in));

  129. if ( rc != 0) {

  130. qDebug() << "Failed to connect!" << rc;

  131. return false;

  132. }

  133. return true;

  134. }

  135.  
  136. bool SftpManager::createSession()

  137. {

  138. int rc = 0;

  139. LIBSSH2_KNOWNHOSTS *nh = nullptr;

  140. size_t len;

  141. int type;

  142. const char *fingerprint;

  143.  
  144. m_session = libssh2_session_init();

  145. if(!m_session){

  146. qDebug() << "Create session instance failed.";

  147. return false;

  148. }

  149.  
  150. /* Since we have set non-blocking, tell libssh2 we are non-blocking */

  151. libssh2_session_set_blocking(m_session, 1);

  152.  
  153. while ((rc = libssh2_session_handshake(m_session, m_socket)) == LIBSSH2_ERROR_EAGAIN);

  154. if(rc){

  155. qDebug() << "Failure establishing SSH session." << rc;

  156. return false;

  157. }

  158.  
  159. fingerprint = libssh2_hostkey_hash(m_session, LIBSSH2_HOSTKEY_HASH_SHA1);

  160. qDebug() << "Fingerprint: ";

  161. for (int i =0; i < 20; i++) {

  162. qDebug() << "%02X " << (unsigned char)fingerprint[i];

  163. }

  164. qDebug() << "\n";

  165. return true;

  166. }

  167.  
  168. bool SftpManager::login(std::string szUserName, std::string szPassword)

  169. {

  170. int rc = 0;

  171. int auth_pw = 1;

  172. if(szUserName == ""){

  173. szUserName = username();

  174. }

  175. if(szPassword == ""){

  176. szPassword = password();

  177. }

  178.  
  179. if(szPassword.size() > 0){

  180. /* We could authenticate via password */

  181. while ((rc = libssh2_userauth_password(m_session, "loohos-01", "liuhe1688")) ==

  182. LIBSSH2_ERROR_EAGAIN);

  183. if (rc) {

  184. qDebug() << "Authentication by password failed.";

  185. shutDown();

  186. return false;

  187. }

  188. }else{

  189. /* Or by public key */

  190. while ((rc = libssh2_userauth_publickey_fromfile(m_session, m_username.c_str(),

  191. "/home/user/"

  192. ".ssh/id_rsa.pub",

  193. "/home/user/"

  194. ".ssh/id_rsa",

  195. m_password.c_str())) ==

  196. LIBSSH2_ERROR_EAGAIN);

  197. if (rc) {

  198. qDebug() << "Authentication by public key failed.";

  199. shutDown();

  200. }

  201. }

  202. return true;

  203. }

  204.  
  205. bool SftpManager::read()

  206. {

  207. LIBSSH2_SFTP *m_sftp_session;

  208. LIBSSH2_SFTP_HANDLE *m_sftp_handle;

  209. int rc,total,spin = 0;

  210. m_sftp_session = libssh2_sftp_init(m_session);

  211. if(!m_sftp_session)

  212. {

  213. qDebug() << "Unable to init SFTP session\n";

  214. shutDown();

  215. }

  216. qDebug() << "libssh2_sftp_open()!\n";

  217. /* Request a file via SFTP */

  218. do{

  219. m_sftp_handle =

  220. libssh2_sftp_open(m_sftp_session, sftppath, LIBSSH2_FXF_READ, 0);

  221. if(!m_sftp_handle)

  222. {

  223. if(libssh2_session_last_errno(m_session) != LIBSSH2_ERROR_EAGAIN){}

  224. qDebug() << "Unable to open file with SFTP\n";

  225. shutDown();

  226. }else {

  227. qDebug() << "non-blocking open\n";

  228. /*waitsocket(m_socket, m_session); *//* now we wait */

  229. }

  230. }while(!m_sftp_handle);

  231. qDebug() << "libssh2_sftp_open() is done, now receive data!\n";

  232. do {

  233. char mem[1024*24];

  234.  
  235. /* loop until we fail */

  236. while ((rc = libssh2_sftp_read(m_sftp_handle, mem,

  237. sizeof(mem))) == LIBSSH2_ERROR_EAGAIN) {

  238. spin++;

  239. waitsocket(m_socket, m_session); /* now we wait */

  240. }

  241. if (rc > 0) {

  242. total += rc;

  243. write(1, mem, rc);

  244. } else {

  245. qDebug() << "the messages with sftp are : " <<mem;

  246. break;

  247. }

  248. } while (1);

  249.  
  250. libssh2_sftp_close(m_sftp_handle);

  251. libssh2_sftp_shutdown(m_sftp_session);

  252. return true;

  253. }

  254.  
  255. bool SftpManager::mkdir()

  256. {

  257.  
  258. LIBSSH2_SFTP *m_sftp_session;

  259. m_sftp_session = libssh2_sftp_init(m_session);

  260. if(!m_sftp_session)

  261. {

  262. qDebug() << "Unable to init SFTP session\n";

  263. shutDown();

  264. }

  265. qDebug() << "libssh2_sftp_open()!\n";

  266. while(libssh2_sftp_mkdir(m_sftp_session,m_sftppath,LIBSSH2_SFTP_S_IRWXU|

  267. LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IXGRP|

  268. LIBSSH2_SFTP_S_IROTH|LIBSSH2_SFTP_S_IXOTH)

  269. == LIBSSH2_ERROR_EAGAIN);

  270.  
  271. libssh2_sftp_shutdown(m_sftp_session);

  272. }

  273.  
  274. bool SftpManager::readAndWrite()

  275. {

  276. char mem[1000];

  277. LIBSSH2_SFTP *m_sftp_session;

  278. LIBSSH2_SFTP_HANDLE *m_sftp_handle;

  279. int rc;

  280. int total,spin = 0;

  281. struct timeval timeout;

  282. fd_set fd;

  283. FILE *tempstorage = NULL;

  284.  
  285.  
  286. tempstorage = fopen(STORAGE, "wb");

  287. if(!tempstorage){

  288. qDebug() << "can't open temp storage file\n" << STORAGE;

  289. shutDown();

  290. }

  291.  
  292. m_sftp_session = libssh2_sftp_init(m_session);

  293. if(!m_sftp_session)

  294. {

  295. qDebug() << "Unable to init SFTP session\n";

  296. shutDown();

  297. }

  298. qDebug() << "libssh2_sftp_open()!\n";

  299. /* Request a file via SFTP */

  300. do{

  301. m_sftp_handle =

  302. libssh2_sftp_open(m_sftp_session, sftppath, LIBSSH2_FXF_READ, 0);

  303. if(!m_sftp_handle)

  304. {

  305. if(libssh2_session_last_errno(m_session) != LIBSSH2_ERROR_EAGAIN){}

  306. qDebug() << "Unable to open file with SFTP\n";

  307. shutDown();

  308. }else {

  309. qDebug() << "non-blocking open\n";

  310. /*waitsocket(m_socket, m_session); *//* now we wait */

  311. }

  312. }while(!m_sftp_handle);

  313. qDebug() << "libssh2_sftp_open() is done, now receive data!\n";

  314.  
  315. do{

  316. do {

  317. rc = libssh2_sftp_read(m_sftp_handle,mem,sizeof (mem));

  318. qDebug() << "libssh2_sftp_read returned %d/n" << rc;

  319. if(rc > 0){

  320. write(2,mem,rc);

  321. fwrite(mem,rc,1,tempstorage);

  322. }

  323. } while (rc>0);

  324. if (rc != LIBSSH2_ERROR_EAGAIN){

  325. break;

  326. }

  327.  
  328. timeout.tv_sec = 10;

  329. timeout.tv_usec = 0;

  330.  
  331. FD_ZERO(&fd);

  332. FD_SET(m_socket,&fd);

  333.  
  334. rc = select(m_socket + 1, &fd, &fd, NULL, &timeout);

  335. if(rc <= 0){

  336. qDebug() << "SFTP download timed out: %d\n" << rc;

  337. break;

  338. }

  339. }while(1);

  340. libssh2_sftp_close(m_sftp_handle);

  341. fclose(tempstorage);

  342.  
  343. tempstorage = fopen(STORAGE, "rb+");

  344. if(!tempstorage){

  345. qDebug() << "can't open %s for reading\n" << STORAGE;

  346. shutDown();

  347. }

  348.  
  349.  
  350. m_sftp_handle =

  351. libssh2_sftp_open(m_sftp_session, m_dest,

  352. LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT,

  353. LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|

  354. LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);

  355. if(m_sftp_handle){

  356. size_t nread;

  357. char *ptr;

  358. do{

  359. nread = fread(mem, 1, sizeof (mem), tempstorage);

  360. if(nread <= 0){

  361. break;

  362. }

  363. ptr = mem;

  364.  
  365. do{

  366. rc = libssh2_sftp_write(m_sftp_handle, ptr, nread);

  367.  
  368. ptr += rc;

  369. nread -= nread;

  370. }while(rc >= 0);

  371. if(rc != LIBSSH2_ERROR_EAGAIN){

  372. break;

  373. }

  374.  
  375. timeout.tv_sec = 10;

  376. timeout.tv_usec = 0;

  377.  
  378. FD_ZERO(&fd);

  379. FD_SET(m_socket,&fd);

  380.  
  381. rc = select(m_socket+1,&fd,&fd,NULL,&timeout);

  382. if(rc <= 0){

  383. qDebug() << "SFTP up;oad timed out: %d\n" << rc ;

  384. break;

  385. }

  386. }while(1);

  387. qDebug() << "SFTP upload done!\n";

  388. }

  389. else {

  390. qDebug() << "SFTP failed to open destination path: %s\n";

  391. }

  392. libssh2_sftp_shutdown(m_sftp_session);

  393. shutDown();

  394. libssh2_session_disconnect(m_session, "Normal Shutdown, Thank you for playing");

  395. libssh2_session_free(m_session);

  396. }

  397.  
  398.  
  399.  
  400. void SftpManager::initConnectionInfo()

  401.  
  402. {

  403. QDomDocument doc;

  404. QFile file("config/sftp.xml");

  405. if(!file.open(QIODevice::ReadOnly)){

  406. return;

  407. }

  408. //read file in doc

  409. if(!doc.setContent(&file)){

  410. file.close();

  411. return;

  412. }

  413. //close file

  414. file.close();

  415. //root element

  416. QDomElement docElement = doc.documentElement();

  417. QDomNodeList nodeList = docElement.elementsByTagName("server");

  418. for(int i = 0; i != nodeList.size(); ++i){

  419. QDomNode node = nodeList.at(i);

  420. if(!node.isNull()){

  421. if(node.isElement()){

  422. QDomElement e = node.toElement();

  423. QDomNodeList ipList = e.elementsByTagName("ipAddress");

  424. QString ipAddress = ipList.at(0).toElement().text();

  425. m_ipAddress = ipAddress.toStdString();

  426. QDomNodeList portList = e.elementsByTagName("port");

  427. int port = portList.at(0).toElement().text().toInt();

  428. m_port = port;

  429. QDomNodeList usernameList = e.elementsByTagName("username");

  430. QString username = usernameList.at(0).toElement().text();

  431. m_username = username.toStdString();

  432. QDomNodeList passwordList = e.elementsByTagName("password");

  433. QString password = passwordList.at(0).toElement().text();

  434. m_password = password.toStdString();

  435. }

  436. }

  437. }

  438. }

  439.  
  440. void SftpManager::shutDown()

  441. {

  442. libssh2_session_disconnect(m_session, "Normal Shutdown, Thank you for playing");

  443. libssh2_session_free(m_session);

  444.  
  445. #ifdef WIN32

  446. closesocket(m_socket);

  447. #else

  448. close(m_socket);

  449. #endif

  450. fprintf(stderr, "all done\n");

  451.  
  452. libssh2_exit();

  453.  
  454. }

  455. std::string SftpManager::ipAddress()

  456. {

  457. if(m_ipAddress == ""){

  458. //initConnectionInfo();

  459. m_ipAddress = "192.168.0.124";

  460. }

  461. return m_ipAddress;

  462. }

  463.  
  464. int SftpManager::port()

  465. {

  466. if(m_port < 1){

  467. //initConnectionInfo();

  468. m_port = 22;

  469. }

  470. return m_port;

  471. }

  472.  
  473. std::string SftpManager::username()

  474. {

  475. if(m_username == ""){

  476. //initConnectionInfo();

  477. m_username = "loohos-01";

  478. }

  479. return m_username;

  480. }

  481.  
  482. std::string SftpManager::password()

  483. {

  484. if(m_password == ""){

  485. //initConnectionInfo();

  486. m_password = "liuhe1688";

  487. }

  488. return m_password;

  489. }

  490.  

使用部分:

 
  1. void TestDialogForm::on_pushButton_5_clicked()

  2. {

  3. SftpManager sftp;

  4. std::string ip = "192.168.0.124";

  5. std::string username = "loohos-01";

  6. std::string password = "liuhe1688";

  7. int port = 22;

  8. /* */

  9. if (!sftp.connect("")){

  10. qDebug() << QString("连接失败"); return;

  11. }

  12.  
  13. if(!sftp.createSession()){

  14. qDebug() << QString("Create session failed.");

  15. return;

  16. }

  17.  
  18. if (!sftp.login(username, password)){

  19. qDebug() << QString("登录失败"); return;

  20. }

  21.  
  22. if (!sftp.mkdir())

  23. {

  24. qDebug() << QString("创建文件夹失败"); return;

  25. }

  26. }

  27.  
  28. void TestDialogForm::on_pushButton_6_clicked()

  29. {

  30. SftpManager sftp;

  31. std::string ip = "192.168.0.124";

  32. std::string username = "loohos-01";

  33. std::string password = "liuhe1688";

  34. int port = 22;

  35. /* */

  36. if (!sftp.connect("")){

  37. qDebug() << QString("连接失败"); return;

  38. }

  39.  
  40. if(!sftp.createSession()){

  41. qDebug() << QString("Create session failed.");

  42. return;

  43. }

  44.  
  45. if (!sftp.login(username, password)){

  46. qDebug() << QString("登录失败"); return;

  47. }

  48.  
  49. if(!sftp.readAndWrite())

  50. {

  51. qDebug() << QString("读写失败"); return;

  52. }

  53. }

总结:积极使用断点,分步了解协议架构,完成开发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值