代码之家  ›  专栏  ›  技术社区  ›  Rob

SFTP C++库?[关闭]

  •  8
  • Rob  · 技术社区  · 16 年前

    有人推荐一个体面的SFTP库来与Windows C++应用程序一起使用吗?如果有跨平台的话,那就更好了,但这并不重要。它是用于商业应用程序的,所以支付费用不是问题。

    我用的是超棒的 Ultimate TCP/IP 支持ftp-s但不支持s ftp的库(是的,我知道,很混乱,不是吗!).

    我遇到了 Chilkat 图书馆,看起来很不错,但不知道还有没有其他人使用过。

    3 回复  |  直到 10 年前
        1
  •  10
  •   Kris Kumler    16 年前

    退房 libcurl .

    libcurl是一个免费且易于使用的客户端URL传输库,支持ftp、ftps、http、https、scp、sftp、tftp、telnet、dict、ldap、ldaps和文件。libcurl支持ssl证书、http-post、http-put、ftp上传、基于http表单的上传、代理、cookie、用户+密码认证(basic、digest、ntlm、negotiate、kerberos4)、文件传输恢复、http代理隧道等!

    libcurl是高度可移植的,它在许多平台上构建和工作相同,包括solaris、netbsd、freebsd、openbsd、darwin、hpux、irix、aix、tru64、linux、unixware、hurd、windows、amiga、os/2、beos、mac os x、ultrix、qnx、openvms、risc os、novell netware、dos等等…

        2
  •  3
  •   Desphilboy    10 年前

    您可以在Windows下对sftp使用libssh。编译时必须有ssh.lib,执行程序时必须有ssh.dll。它对我很有用。这个示例代码是一个使用ssh1的客户机,我还支持大型文件(4GB及更多)和暂停/恢复。 客户机将与任何ssh(和/或sftp)服务器一起工作。由于stackoverflow中消息长度的限制,我无法为您复制整个代码。

    main()
    {
    pSFTPConnector  sshc = new  SFTPConnector(L".\\", L"127.0.0.1", 22, L"sftpuser",L"sftppassword");  // change the hostname , port , username, password to your sftp server, your credentials
    
    FILE *nullfile = fopen("null", "w");  
    sshc->setLogFile(nullfile);
    sshc->setVerbosity(SSH_LOG_DEBUG);  // you can change the verbosity as appropriate for you
    
    int i=  sshc->InitSession();
    if (i != E_OK) wprintf(L"%s",sshc->errstring.c_str() );
    i=sshc->ConnectSession();
    if (i != E_OK) wprintf(L"%s", sshc->errstring.c_str());
    
    i = sshc->InitSFTP();
    if (i != E_OK) wprintf(L"%s", sshc->errstring.c_str());
    
    i = sshc->SFTPrename("renamed_myfile.txt", "myfile.txt");  //change these file names
    i = sshc->Makedir("sftpdir");
    i = sshc->testUploadFile("myfile2.txt", "1234567890testfile");
    
    
    // change these file names to whatever appropriate
    
    
    i = sshc->SFTPreget("c:\\testdir\\reget_downloaded_CAR_HIRE_FINAL.jpg", "CAR_HIRE_FINAL.jpg", 64 * 1024);
    sshc->setBlockTransferDelay(1);
    
    i = sshc->GetSessionStatus();
    i = sshc->SFTPreput("c:\\testdir\\CentOS-6.5-x86_64-bin-DVD1.iso", "reput_CentOS-6.5-x86_64-bin-DVD1.iso", 64 * 1024);
    i = sshc->SFTPreput("c:\\testdir\\Reget_CentOS-6.5-x86_64-bin-DVD1.iso", "reput2_CentOS-6.5-x86_64-bin-DVD1.iso", 64 * 1024);
    
    if (i != E_OK) wprintf(L"%s", sshc->errstring.c_str());
    delete sshc;
    getchar();
    return 0;
    }
    

    这是类文件:

    // filename ssh.h
    // SFTP Connection class with Pause/Resume largfiles capability
    // uses libssh for sftp functionality.
    // Author Desphilboy
    // Written 21 Sep 2014
    
    
    
    
    // needed include files on a windows system
    // for linux, native file open and read/write functions must be changed.
    
    
    #include <libssh\libssh.h>
    #include <libssh\sftp.h>
    #include <Windows.h>
    #include <string>
    #include <fcntl.h>
    #include  <sys\types.h>
    #include <sys\stat.h>
    #include <time.h>
    #include <fstream>
    #include <iostream>
    #include <process.h>
    using namespace std;
    
    
    // constant to limit length of character strings
    #define SHORT_BUFF_LEN          1024
    #define INITIALBLOCKTRANSDELAY          10          // mili seconds, this is the delay that we put after  each block transfer to make it posssible for network to absorb the data.
    
    
    
    
    // these values will be returned by functions to report error or success
    typedef enum sshconerr{
        E_OK = 1, E_SESSION_ALOC = -1, E_SSH_CONNECT_ERR = -2, E_SFTP_ALLOC = -3, E_INIT_SFTP = -4, E_CREATE_DIR = -5, E_FILEOPEN_WRITE = -6, E_WRITE_ERR = -7
        , E_FILE_CLOSE = -8, E_FILE_OPEN_READ = -9, E_INVALID_PARAMS = -10, E_SFTP_ERR = -11, E_SFTP_READ_ERR = -12, E_SFTP_READBYTES_ERR = -13, E_GET_FILEINF = -14
        , E_LOCAL_FILE_NOTFOUND = -15, E_RENAME_ERR = -16, E_MEM_ALLOC = -17, E_LOCAL_FILE_READ = -18, E_LOCAL_FILE_RDWR = -19, E_REMOTEFILE_SEEK = -20
        , E_REMOTE_FILE_OPEN = -21, E_DELETE_ERR = -22, E_RENAME_LOCAL_FILE = -23, E_LOCAL_DELETE_FILE = -24, E_FILEOPEN_RDONLY = -25, E_SFTP_READ_EOF=-26
        ,E_AUTHENTICATE=-27                 ,E_UNKNOWN=-999 } ESSHERR;
    
    
    // status of transfers;
    typedef enum sftpstat{ ES_DONE=0 , ES_INPROGRESS , ES_FAILED, ES_STARTING, ES_PAUSED, ES_RESUMING, ES_CANCELLED,  ES_NONE  } ESFTPSTAT;
    
    using namespace std;
    
    
    
    
    // statistics about the transfer;
    typedef struct transferstatstruct {
        string remote_file_name;
        string local_file_name;
        __int64  initially_transferred;
        __int64  total_size;
        __int64  transferred;
        __int64  averagebps;
        __int64 seconds_elapsed;
        __int64     seconds_remained;
        int percent;    
        ESFTPSTAT transferstate;
    } TTransStat;
    
    
    #define E_SESSION_NEW   -1
    
    
    
    // these libraries are required
    #pragma comment(lib, "ssh.lib")         // for ex4ecution in windows, ssh.dll is needed
    
    
    
    
    // this is the main class that does the majority of the work
    
    typedef class CSFTPConnector{
    
    private:
    
        ssh_session  session;                 // ssh session
        sftp_session sftp;                      // sftp session
        sftp_file file;                         // structure for a remote file
        FILE *localfile;                        // not used in windows but could be local file pointer in UNIX
        FILE *logfile;                          // the file for writing logs, default is set to stderr
        string filename;                        // file name of the transfer;
        string localfilename;                   // file name of local file;
        string      tempfilename;               // a temporaty file name will be used during the transfer which is renamed when transfer is completed.
        ESFTPSTAT transferstatus;               // state of the transfer which has one of the above values (ESFTPSTAT)
    
        __int64 transferstarttime;              // time of start of the transfer
        wchar_t username[SHORT_BUFF_LEN];
        wchar_t password[SHORT_BUFF_LEN];
        wchar_t hostname[SHORT_BUFF_LEN];       // hostname of the sftp server
        wchar_t basedir[SHORT_BUFF_LEN];        // this base dir is the directory of public and private key structur ( NOT USED IN THIS VERSION)
        int port;                               //  port of the server;
        int verbosity;                          //  degree of verbosity of libssh
        __int64  filesize;                      //  total number of bytes to be transfered;
        DWORD  local_file_size_hiDWORD;         //  Bill Gates cannot accept the file size without twisting the programmers, so he accepts them in 2 separate words like this
        DWORD  local_file_size_lowDWORD;        //  these 2 DWORDs when connected together comprise a 64 bit file size.
        __int64 lfilesize;                          // local file size
        __int64 rfilesize;                          // remote file size
        __int64 transfered;                         // number of bytes already transfered
        __int64 initially_was_transferred;          // this is the number of bytes which was transferred before pause or interrupt of a transfer and used when resuming a transfer.
        bool pause;                                 // pause flag
        TTransStat stats;                           // statistics of the transfer
        HANDLE  localfilehandle;                    // windows uses handles to manipulate files. this is the handle to local file.
        int blocktransferdelay;
    
        ESSHERR CSFTPConnector::rwopen_existing_SFTPfile(char *fn);         // open a file on remote ( server ) read/write   for upload
        ESSHERR CSFTPConnector::rdopen_existing_SFTPfile(char *fn);         // open a file on remote ( server ) read only    for download
        ESSHERR createSFTPfile(char *fn);                                   // create a file on server;
        ESSHERR writeSFTPfile(char *block, size_t blocksize);               // write a block of data to the  open remote file
        ESSHERR readSFTPfile(char *block, size_t len, size_t *bytesread);   // read a block of data from the  open remote file
        ESSHERR readSFTPfile(char *block, __int64 len, DWORD *bytesread);
        ESSHERR closeSFTPfile();        // closes the remote file;
        ESSHERR openSFTPfile(char *fn);  // opens the remote file
        ESSHERR getSFTPfileinfo();          // gets information about the remote file
    
    
    public:
        wstring errstring;      // the string describing last error 
        ESSHERR Err;                // error code of last error
        CSFTPConnector();           // default constructor;
        CSFTPConnector(wchar_t *dir, wchar_t *hn, int hostport, wchar_t *un, wchar_t *pass);  // constructor
        void setVerbosity(int v);       
        int  getVerbosity();
        ESSHERR InitSession();          // must be called befor doing any transfer
        ESSHERR ConnectSession();       // connnects to the  ssh server
        ESSHERR InitSFTP();     // must be called befor doing any transfer
        ESSHERR Makedir(char *newdir);
        ESSHERR testUploadFile(char *fn, char *block);          // do not use this , only for test purposes for myself
        ESSHERR SFTPput(char *lfn, char *rfn, size_t blocksize);            // Upload a file from start
        ESSHERR SFTPreput(char *lfn, char *rfn, size_t blocksize);          // checks for previouse interrupted transfer, then either continues the previouse transfer ( if there was any) or starts a new one (UPLOAD)
        ESSHERR SFTPrename(char *newname, char *oldname);                   // renames a remote file( must be closed)
        ESSHERR CSFTPConnector::SFTPdelete(char *remfile);                  // deletes a remote file
        TTransStat *getStatus();                                                // gets statistics of the transfer
        ESSHERR CSFTPConnector::SFTPget(char *lfn, char *rfn, size_t blocksize);    // Downloads a file from  sftp server
        ESSHERR CSFTPConnector::SFTPreget(char *lfn, char *rfn, size_t blocksize);  // checks for previouse interrupted transfer, then either continues the previouse transfer ( if there was any) or starts a new one (DOWNLOAD)
        void    CancelTransfer();
        void    PauseTransfer();
        void    setLogFile(FILE *logf);         // sets the log file, if not set stderr will be used. by default.
        void    CloseLocalFile();
        void    CloseRemoteFile();
        int GetSessionStatus();
        bool  IsConnected(); 
        void setBlockTransferDelay(int miliseconds);
        ESFTPSTAT getTransferStatus();
        ~CSFTPConnector();
    
    
    
    
    } SFTPConnector, *pSFTPConnector ;
    
    
    
    sftpstat CSFTPConnector::getTransferStatus()
    {
        return  transferstatus;
    }
    
    
    void CSFTPConnector::setBlockTransferDelay(int miliseconds)
    {
        blocktransferdelay = miliseconds;
    
    }
    
    
    bool CSFTPConnector::IsConnected()
    {
        if (ssh_is_connected(session) == 1) return true;
        return false;
    }
    
    
    
    int CSFTPConnector::GetSessionStatus()
    {
        return ssh_get_status(session);
    }
    
    void    CSFTPConnector::CloseLocalFile()
    {
        CloseHandle(localfilehandle);
    }
    
    
    void    CSFTPConnector::CloseRemoteFile()
    {
        sftp_close(file);
    }
    
    
    
    void    CSFTPConnector::setLogFile(FILE *logf)
    {
        logfile = logf;
    }
    
    
    void    CSFTPConnector::CancelTransfer()
    {
        transferstatus = ES_CANCELLED;
    
    }
    void    CSFTPConnector::PauseTransfer()
    {
        transferstatus = ES_PAUSED;
        pause = true;
    }
    
    //----------------------------------------
    
    // SFTPreger starts or resumes a download.
    ESSHERR CSFTPConnector::SFTPreget(char *lfn, char *rfn, size_t blocksize)
    {
        ESSHERR     result;
        int rc;
        BOOL  bresult;
        DWORD bytesread;
        DWORD byteswritten;
        filesize = 0;
        transfered = 0;
        initially_was_transferred = 0;
        lfilesize = rfilesize = 0;
        pause = false;
        transferstatus = ES_NONE;
        char *block;
        struct stat st;
        wchar_t temp[SHORT_BUFF_LEN];
        size_t tempsize;
        wstring wlfn;
        int loopcounter = 0;
    
        localfilename = lfn;
        filename = rfn;
    
        tempfilename = string(lfn) + ".sftp_temp";
        mbstowcs_s(&tempsize, temp, tempfilename.c_str(), SHORT_BUFF_LEN);
    
        localfilehandle = CreateFile(temp, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (localfilehandle == INVALID_HANDLE_VALUE)
        {
            transferstatus = ES_FAILED;
            errstring = L"Could not open local file:" + wstring(temp) +L" for read and write";
            Err = E_LOCAL_FILE_RDWR;
            return E_LOCAL_FILE_RDWR;
        }
        local_file_size_lowDWORD = GetFileSize(localfilehandle, &local_file_size_hiDWORD);
        lfilesize = (local_file_size_hiDWORD * 0x100000000) + local_file_size_lowDWORD;
    
        if (lfilesize < 0) {
            transferstatus = ES_FAILED;
            Err = E_LOCAL_FILE_NOTFOUND;
            errstring = L"Could not get size info for file:" + wstring(temp); 
            CloseLocalFile();
            return E_LOCAL_FILE_NOTFOUND;
        }
    
        transfered = lfilesize;
        initially_was_transferred = lfilesize;
    
        __int64 tempi64 = transfered & 0x00000000FFFFFFFF;
        DWORD dwlow = tempi64;
        tempi64 = (transfered  & 0x7FFFFFFF00000000);
        tempi64 = tempi64 >> 32;
        long  dwhi = tempi64;
        DWORD dwResult = SetFilePointer(localfilehandle, dwlow, &dwhi, FILE_BEGIN);
        if (dwResult == INVALID_SET_FILE_POINTER)
        {
            errstring = L"could not set file pointer for localfile" + wstring(temp);
            transferstatus = ES_FAILED; Err = result; 
            CloseLocalFile();
            return result;
        }
    
        block = (char*)malloc(blocksize + 1);
        if (block == NULL) {
            Err = E_MEM_ALLOC;
            transferstatus = ES_FAILED;
            errstring = L"Could not allocate memory for file block size";
            CloseLocalFile();
            return E_MEM_ALLOC;
        }
    
        result = rdopen_existing_SFTPfile((char *)rfn);
    
        if (result == E_OK){
            getSFTPfileinfo();
            filesize = rfilesize;       
        }
        else
        {
            Err = E_REMOTE_FILE_OPEN;
            transferstatus = ES_FAILED;
            errstring = L"Could not open remote file";
            CloseLocalFile();
            delete block;
            return E_REMOTE_FILE_OPEN;
        }
    
    
        rc=sftp_seek64(file, transfered);
        if (rc != SSH_OK)
        {
            Err = E_REMOTEFILE_SEEK;
            transferstatus = ES_FAILED;
            errstring = L"Could not set pointer for remote file";
            CloseRemoteFile();
            CloseLocalFile();
            delete block;
            return E_REMOTEFILE_SEEK;
        }
    
            transferstatus = ES_RESUMING;
    
    
        sftp_file_set_blocking(file);
    
        transferstarttime = time(NULL);
        transferstatus = ES_INPROGRESS;
    
        while (transferstatus != ES_FAILED && transferstatus != ES_PAUSED &&  transferstatus!=ES_CANCELLED  &&transferstatus != ES_DONE)
        {
            loopcounter++;
    
            result = readSFTPfile(block,blocksize, (size_t *) &bytesread);
            if (result != E_OK && result != E_SFTP_READ_EOF)
            {
                errstring = L"Error reading from remote sftp server file.";
                Err = result;
                transferstatus = ES_FAILED;
                CloseRemoteFile();
                CloseLocalFile();
                delete block;
                return result;
            }
            if (result == E_SFTP_READ_EOF)  transferstatus = ES_DONE;
            fprintf(logfile, "Read %d bytes from input file. Number of packets: %d , %llu from %llu bytes\n", bytesread, loopcounter, transfered, filesize);
    
            bresult = WriteFile(localfilehandle, (LPVOID)block, bytesread, &byteswritten, NULL);
            if (byteswritten < bytesread)
            {
                if (bresult == FALSE)
                {
                    errstring = L"Error writing to local file.";
                    Err = E_LOCAL_FILE_RDWR;
                    transferstatus = ES_FAILED;
                    CloseRemoteFile();
                    CloseLocalFile();
                    delete block;
                    return E_LOCAL_FILE_RDWR;
                }
                else if (bytesread == 0)
                {
                    errstring = L"Transfer done.";
                    Err = E_OK;
                    transferstatus = ES_DONE;
                    continue;
                }
            }
    
    
            Err = E_OK;
    
            if (pause == true) transferstatus = ES_PAUSED;
            if (bresult == TRUE &&  bytesread == 0)
            {
                // at the end of the file
                transferstatus = ES_DONE;
            }
            Sleep(blocktransferdelay);
            if (loopcounter % 71 == 0)Sleep(7 * blocktransferdelay);
            if (loopcounter % 331 == 0)Sleep(77 * blocktransferdelay);
            if (loopcounter % 3331 == 0)Sleep(777 * blocktransferdelay);
    
        }
        result = closeSFTPfile();
        CloseHandle(localfilehandle);
        Sleep(1000);
    
        if (transferstatus == ES_DONE)
        {
            wchar_t temp2[SHORT_BUFF_LEN];
            mbstowcs_s(&tempsize, temp2, lfn, SHORT_BUFF_LEN);
            bresult = MoveFile(temp, temp2);
            if (bresult != TRUE)
            {
                Err = E_RENAME_LOCAL_FILE;
                errstring = L"Could not rename local file: " + wstring(temp);
                transferstatus = ES_FAILED;
                delete block;
                return E_RENAME_LOCAL_FILE;
            }
        }
    
        if (transferstatus == ES_CANCELLED)
        {
            wchar_t temp2[SHORT_BUFF_LEN];
            mbstowcs_s(&tempsize, temp2, lfn, SHORT_BUFF_LEN);
            bresult = DeleteFile(temp);
            if (bresult != TRUE)
            {
                Err = E_LOCAL_DELETE_FILE;
                errstring = L"Could not rename local file: " + wstring(temp);
                transferstatus = ES_FAILED;
                delete block;
                return E_LOCAL_DELETE_FILE;
            }
        }
    
        delete block;
        return result;
    }
    
    
    
    
    //---------------------------------------
    
    
    
    TTransStat * CSFTPConnector::getStatus()
    {
        stats.seconds_elapsed = time(NULL); 
        stats.seconds_elapsed -= transferstarttime;
        stats.averagebps = ((transfered- initially_was_transferred) * 8) / stats.seconds_elapsed;
        if (filesize > 0) {
            stats.percent = (transfered *100)/ filesize;
            stats.seconds_remained = ((filesize - transfered) * 8) / stats.averagebps;
        }
        else
        {
            stats.percent = -1;
            stats.seconds_remained = -1;
        }
        stats.total_size = filesize;
        stats.transferstate = transferstatus;
        stats.remote_file_name = filename;
        stats.local_file_name = localfilename;
        stats.transferred = transfered;
        stats.initially_transferred = initially_was_transferred;
    
    
        return &stats;
    }
    
    
    ESSHERR CSFTPConnector::SFTPrename(char *newname, char *oldname)
    {
    
        int rc=sftp_rename(sftp, oldname, newname);
        if (rc !=SSH_OK){
            return E_RENAME_ERR;
        }
    
        return E_OK;
    }
    
    
    
    ESSHERR CSFTPConnector::SFTPdelete(char *remfile)
    {
    
        int rc = sftp_unlink(sftp,remfile);
        if (rc != SSH_OK){
            return E_DELETE_ERR;
        }
    
        return E_OK;
    }
    
    // SFTPreput
    ESSHERR CSFTPConnector::SFTPreput(char *lfn, char *rfn, size_t blocksize)
    {
        ESSHERR     result;
        BOOL  bresult;
        DWORD bytesread;
        filesize = 0;
        transfered = 0;
    
        pause = false;
        transferstatus = ES_NONE;
        char *block;
        struct stat st;
        wchar_t temp[SHORT_BUFF_LEN];
        size_t tempsize;
        wstring wlfn;
        int loopcounter = 0;
    
        localfilename = lfn;
        //wlfn = wstring(lfn);
        //localfile = fopen(lfn, L"r");
        filename = rfn;
        mbstowcs_s(&tempsize, temp, lfn, SHORT_BUFF_LEN);
    
        //filesize = getFileSize(localfilename);
    
        /*if(filesize < 0) {
        transferstatus = ES_FAILED;
        Err = E_LOCAL_FILE_NOTFOUND;
        return E_LOCAL_FILE_NOTFOUND;
        }*/
    
        localfilehandle = CreateFile(temp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (localfilehandle == INVALID_HANDLE_VALUE)
        {
            transferstatus = ES_FAILED;
            Err = E_LOCAL_FILE_NOTFOUND;
            return E_LOCAL_FILE_NOTFOUND;
        }
        local_file_size_lowDWORD = GetFileSize(localfilehandle, &local_file_size_hiDWORD);
        filesize = (local_file_size_hiDWORD * 0x100000000) + local_file_size_lowDWORD;
    
        if (filesize < 0) {
            transferstatus = ES_FAILED;
            Err = E_LOCAL_FILE_NOTFOUND;
            CloseLocalFile();
            return E_LOCAL_FILE_NOTFOUND;
        }
    
        block = (char*)malloc(blocksize + 1);
        if (block == NULL) {
            Err = E_MEM_ALLOC;
            transferstatus = ES_FAILED;
            errstring = L"Could not allocate memory for file block size";
            CloseLocalFile();
            return E_MEM_ALLOC;
        }
    
    
        tempfilename = string(rfn) + ".sftp_temp";
    
        result = rwopen_existing_SFTPfile((char *)tempfilename.c_str());
        if (result == E_OK){
            getSFTPfileinfo();
            sftp_seek64(file, rfilesize);
            __int64 tempi64 = rfilesize & 0x00000000FFFFFFFF;
            DWORD dwlow = tempi64;
            tempi64 = (rfilesize & 0x7FFFFFFF00000000);
            tempi64 = tempi64 >> 32;
            long  dwhi = tempi64;
            DWORD dwResult=SetFilePointer(localfilehandle, dwlow,&dwhi , FILE_BEGIN);
            if (dwResult == INVALID_SET_FILE_POINTER)
            {
                transferstatus = ES_FAILED; Err = result;  return result;
            }
            transferstatus = ES_RESUMING;
            transfered = rfilesize;
            initially_was_transferred = rfilesize;
    
        }
        else{
            result = createSFTPfile((char *)tempfilename.c_str());
            transferstatus = ES_STARTING;
            rfilesize = 0;
            initially_was_transferred = 0;
            if (result != E_OK)  {
                transferstatus = ES_FAILED; 
                Err = result;
                CloseLocalFile();
                return result;
            }
            }
            sftp_file_set_blocking(file);
            transferstarttime = time(NULL);
            transferstatus = ES_INPROGRESS;
    
        while (transferstatus != ES_FAILED && transferstatus != ES_PAUSED && transferstatus != ES_DONE)
        {
            loopcounter++;
            bresult = ReadFile(localfilehandle, (LPVOID)block, blocksize, &bytesread, NULL);
            fprintf(logfile, "Read %d bytes from input file. Number of packets: %d , %llu from %llu bytes\n", bytesread, loopcounter, transfered, filesize);
            if (bytesread < blocksize)
            {
                if (bresult == FALSE)
                {
                    errstring = L"Error reading from local file.";
                    Err = E_LOCAL_FILE_READ;
                    transferstatus = ES_FAILED;
                    CloseRemoteFile();
                    CloseLocalFile();
                    return E_LOCAL_FILE_READ;
                }
                else if (bytesread == 0)
                {
                    errstring = L"Transfer done.";
                    Err = E_OK;
                    transferstatus = ES_DONE;
                    continue;
                }
            }
    
            result = writeSFTPfile(block, bytesread);
            if (result != E_OK && bytesread>0 )
            {
                errstring = L"Error transmitting to remote sftp server file.";
                Err = result;
                transferstatus = ES_FAILED;
                CloseRemoteFile();
                CloseLocalFile();
                return result;
            }
    
    
            Err = E_OK;
            //transfered = transfered + bytesread;
            if (pause == true) transferstatus = ES_PAUSED;
            if (bresult == TRUE &&  bytesread == 0)
            {
                // at the end of the file
                transferstatus = ES_DONE;
            }
            Sleep(blocktransferdelay);
            if (loopcounter % 71 == 0)Sleep(7 * blocktransferdelay);
            if (loopcounter % 331 == 0)Sleep(77 * blocktransferdelay);
            if (loopcounter % 3331 == 0)Sleep(777 * blocktransferdelay);
    
        }
    
        CloseRemoteFile();
        CloseLocalFile();
        Sleep(1000);
    
        if (transferstatus == ES_CANCELLED)
        {
            result = SFTPdelete((char *)tempfilename.c_str());
            if (bresult != E_OK)
            {
                Err = E_DELETE_ERR;
                errstring = L"Could not delete remote file.";
                transferstatus = ES_FAILED;
                return E_DELETE_ERR;
            }
        }
        if (transferstatus == ES_DONE) result = SFTPrename(rfn, (char *)tempfilename.c_str());
        delete block;
        return result;
    }
    
    
    
    
    ESSHERR CSFTPConnector::getSFTPfileinfo()
    {
        sftp_attributes fileinf = sftp_fstat(file);
    
        if (fileinf == NULL){
            return E_GET_FILEINF;
        }
    
        rfilesize = fileinf->size;
    
        sftp_attributes_free(fileinf);
        return E_OK;
    }
    
    ESSHERR CSFTPConnector::closeSFTPfile()
    {
        int rc = sftp_close(file);
        if (rc != SSH_OK)
        {
            fprintf(logfile, "Can't close the written file: %s\n",
                ssh_get_error(session));
            return E_FILE_CLOSE;
        }
        return E_OK;
    }
    
    
    
    
    ESSHERR CSFTPConnector::writeSFTPfile(char *block, size_t blocksize)
    {
        size_t nwritten = sftp_write(file, block, blocksize);
        if (nwritten != blocksize)
        {
            fprintf(logfile, "Can't write data to file: %s\n",
                ssh_get_error(session));
            //sftp_close(file);
            transfered = transfered + nwritten;
            return E_WRITE_ERR;
        }
    
        transfered = transfered + nwritten;
        return E_OK;
    }
    ESSHERR CSFTPConnector::readSFTPfile(char *block, __int64 len, DWORD *bytesread)
    {
        DWORD readbytes;
        *bytesread = 0;
        if (len <= 0) return E_INVALID_PARAMS;
        if (bytesread == NULL || block == NULL) return E_INVALID_PARAMS;
    
        readbytes = sftp_read(file, block, len);
        if (readbytes < 0)
        {
            fprintf(logfile, "Can't read  from  remote file: %s  %s\n", filename.c_str(), ssh_get_error(session));
            *bytesread = 0;
            return E_SFTP_READ_ERR;
        }
    
    
        if (readbytes <  len)
        {
            *bytesread = readbytes;
            return E_SFTP_READ_EOF;
        }
    
    
        *bytesread = readbytes;
        transfered = transfered + readbytes;
    
        return E_OK;
    
    }
    
    
    ESSHERR CSFTPConnector::createSFTPfile(char *fn)
    {
    
        int access_type = O_CREAT | O_RDWR | O_APPEND;
        int rc, nwritten;
    
        filename = string(fn);
        file = sftp_open(sftp, fn,access_type,  S_IREAD | S_IWRITE);
        if (file == NULL)
        {
            fprintf(logfile, "Can't open file for writing: %s\n",
                ssh_get_error(session));
            return E_FILEOPEN_WRITE;
        }
        return E_OK;
    }
    
    
    
    
    
    ESSHERR CSFTPConnector::openSFTPfile(char *fn)
    {
        int access_type = O_RDONLY;
        int rc, nwritten;
    
        filename = string(fn);
        file = sftp_open(sftp, fn,
            access_type, S_IWRITE);
        if (file == NULL)
        {
            fprintf(logfile, "Can't open file for writing: %s\n",
                ssh_get_error(session));
            return E_FILE_OPEN_READ;
        }
        return E_OK;
    
    }
    
    ESSHERR CSFTPConnector::Makedir(char *newdir)
    {
        int rc;
        rc = sftp_mkdir(sftp, newdir, S_IFDIR);
        if (rc != SSH_OK)
        {
            if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
            {
                fprintf(logfile, "Can't create directory: %s\n",
                    ssh_get_error(session));
                return E_CREATE_DIR;
            }
        }
    
            return E_OK;
    }
    
    
    
    
    SFTPConnector::CSFTPConnector()
    {
        //libssh2_init(0);
        session = ssh_new();
        if (session == NULL)
        {
            Err = E_SESSION_ALOC;
            errstring = L"Could not allocate a session.";
    
        }
        wcscpy(hostname, L"localhost" );
        wcscpy(username, L"User");
        wcscpy(password, L"Password");
        wcscpy(basedir, L".\\");
        port = 22;
        verbosity = SSH_LOG_RARE;
        filesize = 0;
        transfered = 0;
    
        pause = false;
        transferstatus = ES_NONE;
        logfile = stderr;
        blocktransferdelay = INITIALBLOCKTRANSDELAY;
    
    }
    
    
    
    
    CSFTPConnector::CSFTPConnector(wchar_t *dir, wchar_t *hn, int hostport, wchar_t *un, wchar_t *pass)
    {
    
        //libssh2_init(0);
        session = ssh_new();
    
        if (session == NULL)
        {
            Err = E_SESSION_ALOC;
            errstring = L"Could not allocate a session.";
    
        }
        wcscpy(hostname, hn);
        wcscpy(username, un);
        wcscpy(password, pass);
        wcscpy(basedir, dir);
        port = hostport;
        verbosity = SSH_LOG_RARE;
         filesize=0;
         transfered=0;
    
         pause=false;
         transferstatus = ES_NONE;
         logfile = stderr;
         blocktransferdelay = INITIALBLOCKTRANSDELAY;
    
    }
    
    
    ESSHERR  CSFTPConnector::InitSFTP()
    {
        int rc;
        sftp= sftp_new(session);
        if (session == NULL)
        {
            Err = E_SFTP_ALLOC;
            errstring = L"Could not allocate a sftp session.";
    
        }
    
        rc = sftp_init(sftp);
        if (rc != SSH_OK)
        {
            fprintf(logfile, "Error initializing SFTP session: %s.\n",
                sftp_get_error(sftp));
            sftp_free(sftp);
            return E_INIT_SFTP;
        }
    
    
        return E_OK;
    }
    
    
    ESSHERR  CSFTPConnector::ConnectSession()
    {
        char temp[SHORT_BUFF_LEN];
        size_t n_of_chars;
        wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)password, SHORT_BUFF_LEN);
        int ir;
    
        ir=ssh_connect(session);
        if (ir != SSH_OK){
            errstring = L"Could not connect the ssh session.";
            return E_SSH_CONNECT_ERR;
        }
    
        ir=ssh_userauth_password(session, NULL, temp);
        if (ir != SSH_OK){
            errstring = L"Could not authenticate with the ssh server.\r\n";
            return E_AUTHENTICATE;
        }
        return E_OK;
    }
    
    
    ESSHERR  CSFTPConnector::InitSession()
    {
        char temp[SHORT_BUFF_LEN];
        size_t n_of_chars;
        wcstombs_s(&n_of_chars, temp,SHORT_BUFF_LEN, (const wchar_t *) hostname, SHORT_BUFF_LEN);
        ssh_options_set(session, SSH_OPTIONS_HOST,temp);
        ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
        ssh_options_set(session, SSH_OPTIONS_PORT, &port);
        wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)username, SHORT_BUFF_LEN);
        ssh_options_set(session, SSH_OPTIONS_USER,temp);
        wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)basedir, SHORT_BUFF_LEN);
        ssh_options_set(session, SSH_OPTIONS_SSH_DIR, temp);
    
        return E_OK;
    }
    
    
    void  CSFTPConnector::setVerbosity(int v)
    {
        verbosity = v;
    }
    
    
    int  CSFTPConnector::getVerbosity()
    {
        return verbosity;
    }
    
        3
  •  2
  •   Adam Rosenfield    16 年前

    OpenSSH 是个不错的选择。它是跨平台的,带有BSD许可证,因此您可以在商业应用程序中使用它,而无需公开源代码。