SFTP客户端代码示例

环境:libssh2 1.4.3、zlib-1.2.8、openssl-1.0.1g

Author: Kagula

最后更新日期:2014-5-18

         从http://www.libssh2.org/下载libssh2-1.4.3.tar.gz文件,解压后打开libssh2.dsw文件升级项目到VisualStudio 2013,里面有两个项目,只要编译libssh2项目就可以了。编译前需要添加zlib和openssl的头文件和库文件链接位置,如果编译libssh2提示找不到msvcrt.lib,为链接库添加下面的路径

C:\Program Files (x86)\Microsoft VisualStudio 12.0\VC\lib

提示找不到ws2_32.lib或odbc32.lib,添加下面的链接路径

C:\Program Files (x86)\MicrosoftSDKs\Windows\v7.1A\Lib

编译通过后文件输出到\libssh2-1.4.3\win32\Release_lib路径下

下面是SFTP客户端示例代码

[cpp]  view plain  copy
 
  1. #include "SFTP_Libssh2.h"  
  2. #include   
  3.   
  4. int main(int argc, char* argv[])  
  5. {  
  6.     //下面的代码只要在进程初始化的时候执行  
  7.     kagula::network::SFTP_Init();  
  8.   
  9.     //测试SFTP链接  
  10.     kagula::network::SFTP_Libssh2* client = kagula::network::SFTP_Libssh2::Inst();  
  11.     std::string ip = "192.168.19.130";  
  12.     uint16_t port = 22;  
  13.     std::string usr = "kagula";  
  14.     std::string pwd = "123456";  
  15.     if (false == client->IsAbilityConn(ip, port, usr, pwd))  
  16.     {  
  17.         std::cout << client->strLastError << std::endl;  
  18.         return -1;  
  19.     }  
  20.   
  21.     //测试文件上传,d:\\temp\\a.html  
  22.     if (0 != client->upload(ip, 22, usr, pwd, "d:\\temp\\a.html""/home/kagula/a.html"))  
  23.     {  
  24.         std::cout << "Error:" << client->strLastError << std::endl;  
  25.     } else  
  26.     {  
  27.         std::cout << client->strLastError << std::endl;  
  28.     }  
  29.       
  30.   
  31.     //测试文件下载  
  32.     if (0 != client->download(ip, 22, usr, pwd, "/home/kagula/a.html","d:\\temp\\b.html" ))  
  33.     {  
  34.         std::cout << "Error:" << client->strLastError << std::endl;  
  35.     }  
  36.     else  
  37.     {  
  38.         std::cout << client->strLastError << std::endl;  
  39.     }  
  40.   
  41.     //进程准备结束,释放资源的时候,运行下面的代码  
  42.     kagula::network::SFTP_Exit();  
  43.     return 0;  
  44. }  

SFTP_Libssh2.h

[cpp]  view plain  copy
 
  1. #pragma once  
  2.   
  3. #include   
  4. #include   
  5.   
  6. /* 
  7. 功能:SFTP协议的文件传输功能 
  8. 最后更新日期:2014-5-17 
  9. 简介:借助Libssh2库很容易实现sftp,ssh2客户端,这里给出 
  10.       如何实现Sftp客户端的代码 
  11. 测试环境:Windows 8.1 64bit、Visual Studio 2013 Professional SP1 
  12.        OpenSSL 1.0.1g、zlib-1.2.8、libssh2  1.4.3 
  13.        Win32控制台项目 
  14. 注意:动态链接需要把“libssh2.dll”文件复制到当前项目路径下 
  15. 说明:原来的代码支持多线程,从应用程序抽出来的时候简化了, 
  16.      你可以修改代码使它同时支持上传或下载多个文件。 
  17. 建议:[1]第三方库直接下载源代码自己编译免得库由于编译器版本的 
  18.      不同或设置的不同链接的时候一大堆麻烦。 
  19.      [2]读懂代码根据项目需求作相应修改 
  20. 补充阅读资料: 
  21. 《使用libssh2库实现支持密码参数的ssh2客户端》 
  22. http://blog.chinaunix.net/uid-24382173-id-229823.html 
  23. */  
  24. namespace kagula {  
  25.     namespace network {  
  26.         int SFTP_Init();  
  27.         void SFTP_Exit();  
  28.   
  29.         class SFTP_BKCall  
  30.         {  
  31.         public:  
  32.             /* progress返回值范围[0.0,1.0] */  
  33.             virtual void OnProgress(float progress) = 0;  
  34.         };  
  35.   
  36.         class SFTP_Libssh2  
  37.         {  
  38.         public:  
  39.             static SFTP_Libssh2* Inst()  
  40.             {  
  41.                 static SFTP_Libssh2 inst;  
  42.   
  43.                 return &inst;  
  44.             }  
  45.   
  46.             /* 
  47.             入口参数使用说明 
  48.             ip:   就填一个IP地址就好了,例如“127.0.0.1”。 
  49.             port: 端口,SFTP服务器默认端口为22。 
  50.             username: 
  51.             password: 
  52.             sftppath: 远程路径“/”开头 ,例如“/a.jpg” 
  53.             localpath: 本地路径,例如“d:\\temp\\test.jpg” 
  54.             strLastError: 错误信息 
  55.  
  56.             出口参数 
  57.             返回不等于零,代表失败! 
  58.             */  
  59.             int upload(std::string ip, unsigned short port, std::string username,  
  60.                 std::string password, std::string localpath, std::string remotepath);  
  61.             int download(std::string ip, unsigned short port, std::string username,  
  62.                 std::string password, std::string sftppath, std::string localpath);  
  63.   
  64.             //测试SFTP服务器是否可以链接  
  65.             bool IsAbilityConn(std::string ip, unsigned short port, std::string username,  
  66.                 std::string password);  
  67.   
  68.             //设置回掉函数  
  69.             void SetBKCall(SFTP_BKCall *bkCall) { m_bkCall = bkCall; }  
  70.   
  71.             //存放最近的错误信息  
  72.             std::string   strLastError;  
  73.   
  74.             //用于停止当前上传或下载线程  
  75.             void stop() { m_isBreak.store(true); }  
  76.         private:  
  77.             SFTP_Libssh2() :m_bkCall(NULL) { m_isBreak.store(false); };//防止直接初始化  
  78.             SFTP_Libssh2(const SFTP_Libssh2&);                 //防止拷贝复制  
  79.             SFTP_Libssh2& operator=(const SFTP_Libssh2&);      //防止分配(运算符函数的调用)  
  80.   
  81.             SFTP_BKCall  *m_bkCall;           
  82.             std::atomic_bool m_isBreak; //带读写保护的bool值  
  83.         };  
  84.     }  
  85. }  


SFTP_Libssh2.cpp

[cpp]  view plain  copy
 
  1. //SFTP_Libssh2.cpp文件清单  
  2. #include "SFTP_Libssh2.h"  
  3.   
  4. #include   
  5. #include   
  6.   
  7. #ifdef HAVE_WINSOCK2_H  
  8. #include   
  9. #endif  
  10. #ifdef HAVE_SYS_SOCKET_H  
  11. #include   
  12. #endif  
  13. #ifdef HAVE_NETINET_IN_H  
  14. #include   
  15. #endif  
  16. #ifdef HAVE_UNISTD_H  
  17. #include   
  18. #endif  
  19. #ifdef HAVE_ARPA_INET_H  
  20. #include   
  21. #endif  
  22. #ifdef HAVE_SYS_TIME_H  
  23. #include   
  24. #endif  
  25.   
  26. #include   
  27. #include   
  28. #include   
  29. #include   
  30. #include   
  31.   
  32. #include   
  33. #include   
  34.   
  35. #pragma comment(lib, "ws2_32.lib")  
  36.   
  37. #pragma comment(lib, "libeay32.lib")    
  38. #pragma comment(lib, "libssh2.lib")    
  39.   
  40. namespace kagula {  
  41.     namespace network  
  42.     {  
  43.         //初始化进程的时候调用  
  44.         //如果非0表示初始化失败!  
  45.         int SFTP_Init()  
  46.         {  
  47.             WSADATA wsadata;  
  48.             int rc = WSAStartup(MAKEWORD(2, 0), &wsadata);  
  49.             if (rc != 0) {  
  50.                 return rc;  
  51.             }  
  52.   
  53.             rc = libssh2_init(0);  
  54.   
  55.             return rc;  
  56.         }  
  57.   
  58.         //进程结束的时候调用  
  59.         void SFTP_Exit()  
  60.         {  
  61.             libssh2_exit();  
  62.   
  63.             WSACleanup();  
  64.         }  
  65.   
  66.         bool SFTP_Libssh2::IsAbilityConn(std::string ip, unsigned short port, std::string username,  
  67.             std::string password)  
  68.         {  
  69.             unsigned long hostaddr;  
  70.             struct sockaddr_in sin;  
  71.             const char *fingerprint;  
  72.             LIBSSH2_SESSION *session;  
  73.             int rc;  
  74.             bool bR = false;  
  75.             FILE *local;  
  76.             LIBSSH2_SFTP *sftp_session;  
  77.             LIBSSH2_SFTP_HANDLE *sftp_handle;  
  78.   
  79.             hostaddr = inet_addr(ip.c_str());//hostaddr = htonl(0x7F000001);  
  80.   
  81.   
  82.             //新建连接  
  83.             int sock = socket(AF_INET, SOCK_STREAM, 0);  
  84.   
  85.             sin.sin_family = AF_INET;  
  86.             sin.sin_port = htons(port);  
  87.             sin.sin_addr.s_addr = hostaddr;  
  88.             if (connect(sock, (struct sockaddr*)(&sin),  
  89.                 sizeof(struct sockaddr_in)) != 0) {  
  90.                 std::ostringstream ostr;  
  91.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "]failed to connect" << ip << "!" << std::endl;  
  92.                 strLastError = ostr.str();  
  93.   
  94.                 return bR;  
  95.             }  
  96.   
  97.             //新建对话实例  
  98.             session = libssh2_session_init();  
  99.             if (!session)  
  100.             {  
  101.                 closesocket(sock);  
  102.                 return bR;  
  103.             }  
  104.   
  105.             //设置调用阻塞  
  106.             libssh2_session_set_blocking(session, 1);  
  107.   
  108.             //进行握手  
  109.             rc = libssh2_session_handshake(session, sock);  
  110.             if (rc) {  
  111.                 std::ostringstream ostr;  
  112.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "]Failure establishing SSH session: " << rc << std::endl;  
  113.                 strLastError = ostr.str();  
  114.   
  115.                 libssh2_session_free(session); closesocket(sock);  
  116.                 return bR;  
  117.             }  
  118.   
  119.             //检查主机指纹  
  120.             std::ostringstream ostr;  
  121.             fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);  
  122.             ostr << "Fingerprint: ";  
  123.             for (int i = 0; i < 20; i++) {  
  124.                 unsigned char c = fingerprint[i];  
  125.                 int nT = c;  
  126.                 ostr << std::hex << std::setw(2) << std::setfill('0') << nT;  
  127.             }  
  128.             strLastError = ostr.str();  
  129.   
  130.             //通过密码验证登陆用户身份  
  131.             if (libssh2_userauth_password(session, username.c_str(), password.c_str())) {  
  132.                 std::ostringstream ostr;  
  133.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "]Authentication by password failed." << std::endl;  
  134.                 strLastError = ostr.str();  
  135.                 goto shutdown;  
  136.             }  
  137.   
  138.             sftp_session = libssh2_sftp_init(session);  
  139.   
  140.             if (!sftp_session) {  
  141.                 std::ostringstream ostr;  
  142.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "]Unable to init SFTP session " << std::endl;  
  143.                 strLastError = ostr.str();  
  144.   
  145.                 goto shutdown;  
  146.             }  
  147.   
  148.             bR = true;  
  149.   
  150.   
  151.             libssh2_sftp_shutdown(sftp_session);  
  152.   
  153.         shutdown:  
  154.             libssh2_session_disconnect(session,  
  155.                 "Normal Shutdown, Thank you for playing");  
  156.             libssh2_session_free(session);  
  157.             closesocket(sock);  
  158.             return bR;  
  159.         }  
  160.   
  161.         /* 
  162.         源码参考地址 
  163.         http://www.libssh2.org/examples/sftp_write.html 
  164.         */  
  165.         int SFTP_Libssh2::upload(std::string ip, unsigned short port, std::string username, std::string password,  
  166.             std::string localpath, std::string remotepath)  
  167.         {  
  168.             if (ip.length()<1 || username.length()<1 || password.length()<1 || localpath.length()<1 || remotepath.length()<1)  
  169.             {  
  170.                 return -1;  
  171.             }  
  172.   
  173.             int nR = 0;  
  174.             unsigned long hostaddr;  
  175.             struct sockaddr_in sin;  
  176.             const char *fingerprint;  
  177.             LIBSSH2_SESSION *session;  
  178.             int rc = -1;  
  179.             FILE *local = NULL;  
  180.             LIBSSH2_SFTP *sftp_session;  
  181.             LIBSSH2_SFTP_HANDLE *sftp_handle;  
  182.   
  183.             hostaddr = inet_addr(ip.c_str());//hostaddr = htonl(0x7F000001);  
  184.   
  185.             if (fopen_s(&local, localpath.c_str(), "rb") != 0) {  
  186.                 std::ostringstream ostr;  
  187.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "]Can't open local file " << localpath << std::endl;  
  188.                 strLastError = ostr.str();  
  189.   
  190.                 return -2;  
  191.             }  
  192.   
  193.             //取待上传文件整个size.  
  194.             fseek(local, 0, SEEK_END);  
  195.             size_t filesize = ftell(local);//local file大小,在readFromDisk中被引用  
  196.             fseek(local, 0, SEEK_SET);//文件指针重置到文件头  
  197.   
  198.             //新建连接  
  199.             int sock = socket(AF_INET, SOCK_STREAM, 0);  
  200.   
  201.             sin.sin_family = AF_INET;  
  202.             sin.sin_port = htons(port);  
  203.             sin.sin_addr.s_addr = hostaddr;  
  204.             if (connect(sock, (struct sockaddr*)(&sin),  
  205.                 sizeof(struct sockaddr_in)) != 0) {  
  206.                 std::ostringstream ostr;  
  207.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] failed to connect " << ip << std::endl;  
  208.                 strLastError = ostr.str();  
  209.   
  210.                 fclose(local);  
  211.                 return -3;  
  212.             }  
  213.   
  214.   
  215.             //创建会话实例  
  216.             session = libssh2_session_init();  
  217.             if (!session)  
  218.             {  
  219.                 fclose(local); closesocket(sock);  
  220.                 return -4;  
  221.             }  
  222.   
  223.             //阻塞方式调用libssh2  
  224.             libssh2_session_set_blocking(session, 1);  
  225.   
  226.             //进行握手  
  227.             rc = libssh2_session_handshake(session, sock);  
  228.             if (rc) {  
  229.                 std::ostringstream ostr;  
  230.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] Failure establishing SSH session:" << rc << std::endl;  
  231.                 strLastError = ostr.str();  
  232.   
  233.                 fclose(local); libssh2_session_free(session); closesocket(sock);  
  234.                 return -5;  
  235.             }  
  236.   
  237.             //获取主机指纹  
  238.             std::ostringstream ostr;  
  239.             fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);  
  240.             ostr << "Fingerprint: ";  
  241.             for (int i = 0; i < 20; i++) {  
  242.                 unsigned char c = fingerprint[i];  
  243.                 int nT = c;//这样转是为了防止符号位扩展  
  244.                 ostr << std::hex << std::setw(2) << std::setfill('0') << nT;  
  245.             }  
  246.             strLastError = ostr.str();  
  247.   
  248.             //通过密码验证  
  249.             if (libssh2_userauth_password(session, username.c_str(), password.c_str())) {  
  250.                 std::ostringstream ostr;  
  251.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] Authentication by password failed ["  
  252.                     << username << "][" << password << "]" << rc << std::endl;  
  253.                 strLastError = ostr.str();  
  254.   
  255.                 goto shutdown;  
  256.             }  
  257.   
  258.             sftp_session = libssh2_sftp_init(session);  
  259.   
  260.             if (!sftp_session) {  
  261.                 std::ostringstream ostr;  
  262.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] Unable to init SFTP session" << std::endl;  
  263.                 strLastError = ostr.str();  
  264.   
  265.                 goto shutdown;  
  266.             }  
  267.   
  268.             //向SFTP服务器发出新建文件请求  
  269.             sftp_handle =  
  270.                 libssh2_sftp_open(sftp_session, remotepath.c_str(),  
  271.                 LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC,  
  272.                 LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR |  
  273.                 LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IROTH);  
  274.   
  275.             if (!sftp_handle) {  
  276.                 std::ostringstream ostr;  
  277.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] Unable to open file with SFTP.  ip="   
  278.                     << ip <<"] remotepath=[" << remotepath << "]" << std::endl;  
  279.                 strLastError = ostr.str();  
  280.   
  281.                 nR = -1;  
  282.   
  283.                 goto shutdown;  
  284.             }  
  285.   
  286.   
  287.             char mem[1024 * 16];  
  288.             size_t nread;  
  289.             char *ptr;  
  290.             size_t count = 0;  
  291.   
  292.             do {  
  293.                 nread = fread(mem, 1, sizeof(mem), local);  
  294.                 if (nread <= 0) {  
  295.                     //到达文件尾部  
  296.                     break;  
  297.                 }  
  298.                 ptr = mem;  
  299.                 do {  
  300.                     // 向服务器写数据,直到数据写完毕  
  301.                     rc = libssh2_sftp_write(sftp_handle, ptr, nread);  
  302.                     if (rc < 0)  
  303.                         break;  
  304.                     ptr += rc; count += nread;  
  305.                     nread -= rc;  
  306.   
  307.                     //如果设置了回调,进行回调  
  308.                     if (m_bkCall)  
  309.                     {  
  310.                         float p = count / (float)filesize;  
  311.                         m_bkCall->OnProgress(p);  
  312.                     }  
  313.                     //callback.end  
  314.                 } while (nread);  
  315.   
  316.                 if ( m_isBreak.load() == true )  
  317.                 {  
  318.                     std::ostringstream ostr;  
  319.                     ostr << "[" << __FILE__ << "][" << __LINE__ << "] 上传文件任务被用户break!" << std::endl;  
  320.                     strLastError = ostr.str();  
  321.   
  322.                     nR = -6;  
  323.                     break;  
  324.                 }  
  325.             } while (rc > 0);  
  326.   
  327.             libssh2_sftp_close(sftp_handle);  
  328.             libssh2_sftp_shutdown(sftp_session);  
  329.   
  330.         shutdown:  
  331.             libssh2_session_disconnect(session,  
  332.                 "Normal Shutdown, Thank you for playing");  
  333.             libssh2_session_free(session);  
  334.   
  335.             closesocket(sock);  
  336.   
  337.             fclose(local);  
  338.   
  339.             return nR;//返回“0”表示成功  
  340.         }  
  341.   
  342.         /* 
  343.         源码参考地址 
  344.         http://www.oschina.net/code/snippet_12_10717 
  345.         */  
  346.         int SFTP_Libssh2::download(std::string ip, unsigned short port, std::string username, std::string password,  
  347.             std::string sftppath, std::string localpath)  
  348.         {  
  349.             unsigned long hostaddr;  
  350.             int sock, i, auth_pw = 0;  
  351.             struct sockaddr_in sin;  
  352.             const char *fingerprint;  
  353.             char *userauthlist;  
  354.             LIBSSH2_SESSION *session;  
  355.             int rc;  
  356.             LIBSSH2_SFTP *sftp_session;  
  357.             LIBSSH2_SFTP_HANDLE *sftp_handle;  
  358.   
  359.             hostaddr = inet_addr(ip.c_str()); //hostaddr = htonl(0x7F000001);  
  360.   
  361.             /* 
  362.             * The application code is responsible for creating the socket 
  363.             * and establishing the connection 
  364.             */  
  365.             sock = socket(AF_INET, SOCK_STREAM, 0);  
  366.   
  367.             sin.sin_family = AF_INET;  
  368.             sin.sin_port = htons(port);  
  369.             sin.sin_addr.s_addr = hostaddr;  
  370.             if (connect(sock, (struct sockaddr*)(&sin),  
  371.                 sizeof(struct sockaddr_in)) != 0) {  
  372.                 std::ostringstream ostr;  
  373.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] 连接失败!" << std::endl;  
  374.                 strLastError = ostr.str();  
  375.                 return -1;  
  376.             }  
  377.   
  378.             /* Create a session instance 
  379.             */  
  380.             session = libssh2_session_init();  
  381.   
  382.             if (!session)  
  383.                 return -1;  
  384.   
  385.             /* Since we have set non-blocking, tell libssh2 we are blocking */  
  386.             libssh2_session_set_blocking(session, 1);  
  387.   
  388.   
  389.             /* ... start it up. This will trade welcome banners, exchange keys, 
  390.             * and setup crypto, compression, and MAC layers 
  391.             */  
  392.             rc = libssh2_session_handshake(session, sock);  
  393.   
  394.             if (rc) {  
  395.                 std::ostringstream ostr;  
  396.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] 建立SSH会话失败" << rc << std::endl;  
  397.                 strLastError = ostr.str();  
  398.   
  399.                 return -1;  
  400.             }  
  401.   
  402.             /* At this point we havn't yet authenticated.  The first thing to do 
  403.             * is check the hostkey's fingerprint against our known hosts Your app 
  404.             * may have it hard coded, may go to a file, may present it to the 
  405.             * user, that's your call 
  406.             */  
  407.             fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);  
  408.   
  409.             std::ostringstream ostr;  
  410.             fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);  
  411.             ostr << "Fingerprint: ";  
  412.             for (int i = 0; i < 20; i++) {  
  413.                 unsigned char c = fingerprint[i];  
  414.                 int nT = c;  
  415.                 ostr << std::hex << std::setw(2) << std::setfill('0') << nT;  
  416.             }  
  417.             strLastError = ostr.str();  
  418.   
  419.             /* check what authentication methods are available */  
  420.             userauthlist = libssh2_userauth_list(session, username.c_str(), username.length());  
  421.             if (strstr(userauthlist, "password") == NULL)  
  422.             {  
  423.                 std::ostringstream ostr;  
  424.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] 服务器不支持输入password方式验证!" << std::endl;  
  425.                 strLastError = ostr.str();  
  426.                 goto shutdown;  
  427.             }  
  428.   
  429.             /* We could authenticate via password */  
  430.             if (libssh2_userauth_password(session, username.c_str(), password.c_str())) {  
  431.   
  432.                 std::ostringstream ostr;  
  433.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] 密码错误!" << std::endl;  
  434.                 strLastError = ostr.str();  
  435.                 goto shutdown;  
  436.             }  
  437.   
  438.             sftp_session = libssh2_sftp_init(session);  
  439.             if (!sftp_session) {  
  440.                 std::ostringstream ostr;  
  441.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] 初始化FTL对话失败!" << std::endl;  
  442.                 strLastError = ostr.str();  
  443.                 goto shutdown;  
  444.             }  
  445.   
  446.             /* Request a file via SFTP */  
  447.             sftp_handle =  
  448.                 libssh2_sftp_open(sftp_session, sftppath.c_str(), LIBSSH2_FXF_READ, 0);  
  449.   
  450.   
  451.             if (!sftp_handle) {  
  452.                 std::ostringstream ostr;  
  453.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] 打开文件失败! " << libssh2_sftp_last_error(sftp_session) << std::endl;  
  454.                 strLastError = ostr.str();  
  455.   
  456.                 goto shutdown;  
  457.             }  
  458.   
  459.             FILE *stream;  
  460.             if (fopen_s(&stream, localpath.c_str(), "wb") == 0)  
  461.             {  
  462.                 do {  
  463.                     char mem[1024];  
  464.   
  465.                     /* loop until we fail */  
  466.                     rc = libssh2_sftp_read(sftp_handle, mem, sizeof(mem));  
  467.   
  468.                     if (rc > 0) {  
  469.                         //从内存到磁盘  
  470.                         fwrite(mem, 1, rc, stream);  
  471.                     }  
  472.                     else {  
  473.                         break;  
  474.                     }  
  475.                 } while (1);  
  476.   
  477.                 fclose(stream);  
  478.             }  
  479.             else {  
  480.                 std::ostringstream ostr;  
  481.                 ostr << "[" << __FILE__ << "][" << __LINE__ << "] 新建本地文件失败 " << localpath << std::endl;  
  482.                 strLastError = ostr.str();  
  483.             }  
  484.   
  485.             libssh2_sftp_close(sftp_handle);  
  486.   
  487.             libssh2_sftp_shutdown(sftp_session);  
  488.   
  489.         shutdown:  
  490.   
  491.             libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing");  
  492.             libssh2_session_free(session);  
  493.   
  494.             closesocket(sock);//INVALID_SOCKET  
  495.   
  496.             return 0;  
  497.         }  
  498.     }  

你可能感兴趣的:(SFTP客户端代码示例)