最近涉及到sftp通信编码。上传测试代码记录一下。
头文件:
-
#ifndef SFTPMANAGER_H
-
#define SFTPMANAGER_H
-
#ifdef WIN32
-
#include "libssh2/win32/libssh2_config.h"
-
#endif
-
#include <mutex>
-
#include <memory>
-
#include <QThread>
-
#include <iostream>
-
#include <vector>
-
#include <libssh2/libssh2.h>
-
#ifdef WIN32
-
#include <windows.h>
-
#include <winsock2.h>
-
#pragma comment(lib, "Ws2_32.lib")
-
#else
-
#include <sys/socket.h>
-
#include <unistd.h>
-
#include <arpa/inet.h>
-
#endif
-
class SftpManager
-
{
-
public:
-
SftpManager();
-
virtual ~SftpManager();
-
bool connect(std::string szIp, int nPort = 22);
-
bool createSession();
-
bool login(std::string szUserName, std::string szPassword);
-
bool read();
-
bool mkdir();
-
bool readAndWrite();
-
private:
-
SOCKET m_socket;
-
LIBSSH2_SESSION *m_session = nullptr;
-
std::vector<LIBSSH2_CHANNEL*> m_channels;
-
//std::vector<std::mutex *> m_channel_mutexs;
-
std::vector<std::shared_ptr<std::mutex>> m_channel_mutexs;
-
static std::string m_ipAddress;
-
static int m_port;
-
static std::string m_username;
-
static std::string m_password;
-
static void initConnectionInfo();
-
static int waitsocket(int socket_fd, LIBSSH2_SESSION *session);
-
void shutDown();
-
static std::string ipAddress();
-
static std::string username();
-
static std::string password();
-
static int port();
-
};
-
#endif // SFTPMANAGER_H
源文件:
-
#include "SftpManager.h"
-
#include <QtXml>
-
#include <libssh2/libssh2_sftp.h>
-
#define STORAGE "d:\\src\\test.txt"
-
std::string SftpManager::m_password;
-
std::string SftpManager::m_username;
-
std::string SftpManager::m_ipAddress;
-
int SftpManager::m_port;
-
const char *sftppath = "/home/loohos-01/abc/test";
-
const char *m_sftppath = "/home/loohos-01/abc/test_mkdir";
-
const char *m_dest = "/home/loohos-01/abc/test_dest";
-
SftpManager::SftpManager()
-
{
-
}
-
SftpManager::~SftpManager()
-
{
-
if (!m_channels.empty()){
-
for (auto channel : m_channels) if (nullptr != channel) libssh2_channel_free(channel);
-
m_channels.clear();
-
}
-
/*
-
if (!m_channel_mutexs.empty()){
-
for (auto mtx : m_channel_mutexs) delete mtx;
-
m_channel_mutexs.clear();
-
}
-
*/
-
if (nullptr != m_session){
-
libssh2_session_disconnect(m_session, "Bye bye, Thank you");
-
libssh2_session_free(m_session);
-
m_session = nullptr;
-
}
-
libssh2_exit();
-
if (INVALID_SOCKET != m_socket) closesocket(m_socket);
-
#ifdef WIN32
-
WSACleanup();
-
#endif
-
}
-
int SftpManager::waitsocket(int socket_fd, LIBSSH2_SESSION *session )
-
{
-
struct timeval timeout;
-
int rc;
-
fd_set fd;
-
fd_set *writefd = NULL;
-
fd_set *readfd = NULL;
-
int dir;
-
timeout.tv_sec = 10;
-
timeout.tv_usec = 0;
-
FD_ZERO(&fd);
-
FD_SET(socket_fd, &fd);
-
dir = libssh2_session_block_directions(session);
-
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
-
readfd = &fd;
-
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
-
writefd = &fd;
-
rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);
-
return rc;
-
}
-
bool SftpManager::connect(std::string szIp, int nPort)
-
{
-
unsigned long hostaddr;
-
int sock, i, auth_pw = 1;
-
struct sockaddr_in sin;
-
const char *fingerprint;
-
LIBSSH2_SESSION *session;
-
const char *username = "loohos-01";
-
const char *password = "liuhe1688";
-
#ifdef HAVE_GETTIMEOFDAY
-
struct timeval start;
-
struct timeval end;
-
long time_ms;
-
#endif
-
int rc;
-
int total = 0;
-
int spin = 0;
-
LIBSSH2_SFTP *sftp_session;
-
LIBSSH2_SFTP_HANDLE *sftp_handle;
-
#ifdef WIN32
-
WSADATA wsadata;
-
int err;
-
err = WSAStartup(MAKEWORD(2,0), &wsadata);
-
if(err != 0)
-
{
-
qDebug() << "WSAStartup failed with error:" << err;
-
return false;
-
}
-
#endif
-
if(szIp == ""){
-
szIp = ipAddress();
-
}
-
if(nPort < 1){
-
nPort = port();
-
}
-
rc = libssh2_init(0);
-
if(rc != 0){
-
qDebug() << "libssh2 initialization failed." << rc;
-
return false;
-
}
-
hostaddr = inet_addr(szIp.c_str());
-
m_socket = socket(AF_INET, SOCK_STREAM, 0);
-
sin.sin_family = AF_INET;
-
sin.sin_port = htons(22);
-
sin.sin_addr.s_addr = hostaddr;
-
rc = ::connect(m_socket, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in));
-
if ( rc != 0) {
-
qDebug() << "Failed to connect!" << rc;
-
return false;
-
}
-
return true;
-
}
-
bool SftpManager::createSession()
-
{
-
int rc = 0;
-
LIBSSH2_KNOWNHOSTS *nh = nullptr;
-
size_t len;
-
int type;
-
const char *fingerprint;
-
m_session = libssh2_session_init();
-
if(!m_session){
-
qDebug() << "Create session instance failed.";
-
return false;
-
}
-
/* Since we have set non-blocking, tell libssh2 we are non-blocking */
-
libssh2_session_set_blocking(m_session, 1);
-
while ((rc = libssh2_session_handshake(m_session, m_socket)) == LIBSSH2_ERROR_EAGAIN);
-
if(rc){
-
qDebug() << "Failure establishing SSH session." << rc;
-
return false;
-
}
-
fingerprint = libssh2_hostkey_hash(m_session, LIBSSH2_HOSTKEY_HASH_SHA1);
-
qDebug() << "Fingerprint: ";
-
for (int i =0; i < 20; i++) {
-
qDebug() << "%02X " << (unsigned char)fingerprint[i];
-
}
-
qDebug() << "\n";
-
return true;
-
}
-
bool SftpManager::login(std::string szUserName, std::string szPassword)
-
{
-
int rc = 0;
-
int auth_pw = 1;
-
if(szUserName == ""){
-
szUserName = username();
-
}
-
if(szPassword == ""){
-
szPassword = password();
-
}
-
if(szPassword.size() > 0){
-
/* We could authenticate via password */
-
while ((rc = libssh2_userauth_password(m_session, "loohos-01", "liuhe1688")) ==
-
LIBSSH2_ERROR_EAGAIN);
-
if (rc) {
-
qDebug() << "Authentication by password failed.";
-
shutDown();
-
return false;
-
}
-
}else{
-
/* Or by public key */
-
while ((rc = libssh2_userauth_publickey_fromfile(m_session, m_username.c_str(),
-
"/home/user/"
-
".ssh/id_rsa.pub",
-
"/home/user/"
-
".ssh/id_rsa",
-
m_password.c_str())) ==
-
LIBSSH2_ERROR_EAGAIN);
-
if (rc) {
-
qDebug() << "Authentication by public key failed.";
-
shutDown();
-
}
-
}
-
return true;
-
}
-
bool SftpManager::read()
-
{
-
LIBSSH2_SFTP *m_sftp_session;
-
LIBSSH2_SFTP_HANDLE *m_sftp_handle;
-
int rc,total,spin = 0;
-
m_sftp_session = libssh2_sftp_init(m_session);
-
if(!m_sftp_session)
-
{
-
qDebug() << "Unable to init SFTP session\n";
-
shutDown();
-
}
-
qDebug() << "libssh2_sftp_open()!\n";
-
/* Request a file via SFTP */
-
do{
-
m_sftp_handle =
-
libssh2_sftp_open(m_sftp_session, sftppath, LIBSSH2_FXF_READ, 0);
-
if(!m_sftp_handle)
-
{
-
if(libssh2_session_last_errno(m_session) != LIBSSH2_ERROR_EAGAIN){}
-
qDebug() << "Unable to open file with SFTP\n";
-
shutDown();
-
}else {
-
qDebug() << "non-blocking open\n";
-
/*waitsocket(m_socket, m_session); *//* now we wait */
-
}
-
}while(!m_sftp_handle);
-
qDebug() << "libssh2_sftp_open() is done, now receive data!\n";
-
do {
-
char mem[1024*24];
-
/* loop until we fail */
-
while ((rc = libssh2_sftp_read(m_sftp_handle, mem,
-
sizeof(mem))) == LIBSSH2_ERROR_EAGAIN) {
-
spin++;
-
waitsocket(m_socket, m_session); /* now we wait */
-
}
-
if (rc > 0) {
-
total += rc;
-
write(1, mem, rc);
-
} else {
-
qDebug() << "the messages with sftp are : " <<mem;
-
break;
-
}
-
} while (1);
-
libssh2_sftp_close(m_sftp_handle);
-
libssh2_sftp_shutdown(m_sftp_session);
-
return true;
-
}
-
bool SftpManager::mkdir()
-
{
-
LIBSSH2_SFTP *m_sftp_session;
-
m_sftp_session = libssh2_sftp_init(m_session);
-
if(!m_sftp_session)
-
{
-
qDebug() << "Unable to init SFTP session\n";
-
shutDown();
-
}
-
qDebug() << "libssh2_sftp_open()!\n";
-
while(libssh2_sftp_mkdir(m_sftp_session,m_sftppath,LIBSSH2_SFTP_S_IRWXU|
-
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IXGRP|
-
LIBSSH2_SFTP_S_IROTH|LIBSSH2_SFTP_S_IXOTH)
-
== LIBSSH2_ERROR_EAGAIN);
-
libssh2_sftp_shutdown(m_sftp_session);
-
}
-
bool SftpManager::readAndWrite()
-
{
-
char mem[1000];
-
LIBSSH2_SFTP *m_sftp_session;
-
LIBSSH2_SFTP_HANDLE *m_sftp_handle;
-
int rc;
-
int total,spin = 0;
-
struct timeval timeout;
-
fd_set fd;
-
FILE *tempstorage = NULL;
-
tempstorage = fopen(STORAGE, "wb");
-
if(!tempstorage){
-
qDebug() << "can't open temp storage file\n" << STORAGE;
-
shutDown();
-
}
-
m_sftp_session = libssh2_sftp_init(m_session);
-
if(!m_sftp_session)
-
{
-
qDebug() << "Unable to init SFTP session\n";
-
shutDown();
-
}
-
qDebug() << "libssh2_sftp_open()!\n";
-
/* Request a file via SFTP */
-
do{
-
m_sftp_handle =
-
libssh2_sftp_open(m_sftp_session, sftppath, LIBSSH2_FXF_READ, 0);
-
if(!m_sftp_handle)
-
{
-
if(libssh2_session_last_errno(m_session) != LIBSSH2_ERROR_EAGAIN){}
-
qDebug() << "Unable to open file with SFTP\n";
-
shutDown();
-
}else {
-
qDebug() << "non-blocking open\n";
-
/*waitsocket(m_socket, m_session); *//* now we wait */
-
}
-
}while(!m_sftp_handle);
-
qDebug() << "libssh2_sftp_open() is done, now receive data!\n";
-
do{
-
do {
-
rc = libssh2_sftp_read(m_sftp_handle,mem,sizeof (mem));
-
qDebug() << "libssh2_sftp_read returned %d/n" << rc;
-
if(rc > 0){
-
write(2,mem,rc);
-
fwrite(mem,rc,1,tempstorage);
-
}
-
} while (rc>0);
-
if (rc != LIBSSH2_ERROR_EAGAIN){
-
break;
-
}
-
timeout.tv_sec = 10;
-
timeout.tv_usec = 0;
-
FD_ZERO(&fd);
-
FD_SET(m_socket,&fd);
-
rc = select(m_socket + 1, &fd, &fd, NULL, &timeout);
-
if(rc <= 0){
-
qDebug() << "SFTP download timed out: %d\n" << rc;
-
break;
-
}
-
}while(1);
-
libssh2_sftp_close(m_sftp_handle);
-
fclose(tempstorage);
-
tempstorage = fopen(STORAGE, "rb+");
-
if(!tempstorage){
-
qDebug() << "can't open %s for reading\n" << STORAGE;
-
shutDown();
-
}
-
m_sftp_handle =
-
libssh2_sftp_open(m_sftp_session, m_dest,
-
LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT,
-
LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
-
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
-
if(m_sftp_handle){
-
size_t nread;
-
char *ptr;
-
do{
-
nread = fread(mem, 1, sizeof (mem), tempstorage);
-
if(nread <= 0){
-
break;
-
}
-
ptr = mem;
-
do{
-
rc = libssh2_sftp_write(m_sftp_handle, ptr, nread);
-
ptr += rc;
-
nread -= nread;
-
}while(rc >= 0);
-
if(rc != LIBSSH2_ERROR_EAGAIN){
-
break;
-
}
-
timeout.tv_sec = 10;
-
timeout.tv_usec = 0;
-
FD_ZERO(&fd);
-
FD_SET(m_socket,&fd);
-
rc = select(m_socket+1,&fd,&fd,NULL,&timeout);
-
if(rc <= 0){
-
qDebug() << "SFTP up;oad timed out: %d\n" << rc ;
-
break;
-
}
-
}while(1);
-
qDebug() << "SFTP upload done!\n";
-
}
-
else {
-
qDebug() << "SFTP failed to open destination path: %s\n";
-
}
-
libssh2_sftp_shutdown(m_sftp_session);
-
shutDown();
-
libssh2_session_disconnect(m_session, "Normal Shutdown, Thank you for playing");
-
libssh2_session_free(m_session);
-
}
-
void SftpManager::initConnectionInfo()
-
{
-
QDomDocument doc;
-
QFile file("config/sftp.xml");
-
if(!file.open(QIODevice::ReadOnly)){
-
return;
-
}
-
//read file in doc
-
if(!doc.setContent(&file)){
-
file.close();
-
return;
-
}
-
//close file
-
file.close();
-
//root element
-
QDomElement docElement = doc.documentElement();
-
QDomNodeList nodeList = docElement.elementsByTagName("server");
-
for(int i = 0; i != nodeList.size(); ++i){
-
QDomNode node = nodeList.at(i);
-
if(!node.isNull()){
-
if(node.isElement()){
-
QDomElement e = node.toElement();
-
QDomNodeList ipList = e.elementsByTagName("ipAddress");
-
QString ipAddress = ipList.at(0).toElement().text();
-
m_ipAddress = ipAddress.toStdString();
-
QDomNodeList portList = e.elementsByTagName("port");
-
int port = portList.at(0).toElement().text().toInt();
-
m_port = port;
-
QDomNodeList usernameList = e.elementsByTagName("username");
-
QString username = usernameList.at(0).toElement().text();
-
m_username = username.toStdString();
-
QDomNodeList passwordList = e.elementsByTagName("password");
-
QString password = passwordList.at(0).toElement().text();
-
m_password = password.toStdString();
-
}
-
}
-
}
-
}
-
void SftpManager::shutDown()
-
{
-
libssh2_session_disconnect(m_session, "Normal Shutdown, Thank you for playing");
-
libssh2_session_free(m_session);
-
#ifdef WIN32
-
closesocket(m_socket);
-
#else
-
close(m_socket);
-
#endif
-
fprintf(stderr, "all done\n");
-
libssh2_exit();
-
}
-
std::string SftpManager::ipAddress()
-
{
-
if(m_ipAddress == ""){
-
//initConnectionInfo();
-
m_ipAddress = "192.168.0.124";
-
}
-
return m_ipAddress;
-
}
-
int SftpManager::port()
-
{
-
if(m_port < 1){
-
//initConnectionInfo();
-
m_port = 22;
-
}
-
return m_port;
-
}
-
std::string SftpManager::username()
-
{
-
if(m_username == ""){
-
//initConnectionInfo();
-
m_username = "loohos-01";
-
}
-
return m_username;
-
}
-
std::string SftpManager::password()
-
{
-
if(m_password == ""){
-
//initConnectionInfo();
-
m_password = "liuhe1688";
-
}
-
return m_password;
-
}
使用部分:
-
void TestDialogForm::on_pushButton_5_clicked()
-
{
-
SftpManager sftp;
-
std::string ip = "192.168.0.124";
-
std::string username = "loohos-01";
-
std::string password = "liuhe1688";
-
int port = 22;
-
/* */
-
if (!sftp.connect("")){
-
qDebug() << QString("连接失败"); return;
-
}
-
if(!sftp.createSession()){
-
qDebug() << QString("Create session failed.");
-
return;
-
}
-
if (!sftp.login(username, password)){
-
qDebug() << QString("登录失败"); return;
-
}
-
if (!sftp.mkdir())
-
{
-
qDebug() << QString("创建文件夹失败"); return;
-
}
-
}
-
void TestDialogForm::on_pushButton_6_clicked()
-
{
-
SftpManager sftp;
-
std::string ip = "192.168.0.124";
-
std::string username = "loohos-01";
-
std::string password = "liuhe1688";
-
int port = 22;
-
/* */
-
if (!sftp.connect("")){
-
qDebug() << QString("连接失败"); return;
-
}
-
if(!sftp.createSession()){
-
qDebug() << QString("Create session failed.");
-
return;
-
}
-
if (!sftp.login(username, password)){
-
qDebug() << QString("登录失败"); return;
-
}
-
if(!sftp.readAndWrite())
-
{
-
qDebug() << QString("读写失败"); return;
-
}
-
}
总结:积极使用断点,分步了解协议架构,完成开发。