网站怎么做万词,aso排名,自己建一个外贸网站,东莞做网站 自媒体知识点SSH的全称是Secure Shell#xff0c;安全外壳协议#xff0c;从中可以知道#xff0c;其实就是套了个壳。以前说过一个过时的协议FTP。但当加上这个SSH后就变成了SFTP#xff0c;简单理解就说FTP套了一个SSH。这里以SSH2开源库为例#xff0c;演示了使用C Qt框架安全外壳协议从中可以知道其实就是套了个壳。以前说过一个过时的协议FTP。但当加上这个SSH后就变成了SFTP简单理解就说FTP套了一个SSH。这里以SSH2开源库为例演示了使用C Qt框架连接服务器并上传文件的过程。还有个重要的知识点QTcpSocket中的socketDescriptor()返回的是底层操作系统的原始套接字描述符socket descriptor。可以将这个描述符给到SSH2框架中进行外壳安全。流程使用SSH2的通用流程如下A. 初始化 libssh2// 初始化 libssh2 int rc libssh2_init(0);B. 建立 TCP 连接// 建立 TCP 连接 m_socket-connectToHost(host, port);C. 初始化 SSH 会话// 初始化 SSH 会话 m_session libssh2_session_init();D. 进行 SSH 握手// 进行 SSH 握手 int rc libssh2_session_handshake(m_session, m_socket-socketDescriptor());E. 密码认证// 密码认证 rc libssh2_userauth_password(m_session, username.toUtf8().constData(), password.toUtf8().constData());F. 初始化 SFTP 会话// 初始化 SFTP 会话 LIBSSH2_SFTP *sftp libssh2_sftp_init(m_session);G. 创建远程文件写模式权限 0644// 创建远程文件写模式权限 0644 LIBSSH2_SFTP_HANDLE *sftpHandle libssh2_sftp_open(sftp, remoteFilePath.toUtf8().constData(), LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC, 0644);H. 上传写入远程文件// 写入远程文件 ssize_t bytesWritten libssh2_sftp_write(sftpHandle, buffer, bytesRead);I. 清理资源// 清理资源 libssh2_sftp_close(sftpHandle); libssh2_sftp_shutdown(sftp); libssh2_session_disconnect(m_session, 文件上传完成); libssh2_session_free(m_session);代码及运行SFTPDemo.proQT - gui QT network CONFIG c11 console CONFIG - app_bundle # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES QT_DISABLE_DEPRECATED_BEFORE0x060000 # disables all the APIs deprecated before Qt 6.0.0 INCLUDEPATH D:\Github\libssh2-1.11.1\libssh2-1.11.1\include SOURCES \ SftpUploader.cpp \ main.cpp # Default rules for deployment. qnx: target.path /tmp/$${TARGET}/bin else: unix:!android: target.path /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS target # 区分debug和release模式链接不同版本的库 CONFIG(debug, debug|release) { # Debug模式配置 message(Configuring for Debug mode) # Debug库路径通常包含debug目录或带d后缀的库 LIBS -LD:/Github/libssh2-1.11.1/libssh2-1.11.1/build/src/Debug # 替换为debug库路径 # Debug版本库示例libssh的debug版本可能名为libssh_d或ssh_d LIBS -llibssh2 # 假设debug库带d后缀 } else { # Release模式配置 message(Configuring for Release mode) # Release库路径 LIBS -LD:/Github/libssh2-1.11.1/libssh2-1.11.1/build/src/Release # 替换为release库路径 # Release版本库无后缀 LIBS -llibssh2 } HEADERS \ SftpUploader.hSftpUploader.h#ifndef SFTP_UPLOADER_H #define SFTP_UPLOADER_H #include QObject #include QTcpSocket #include libssh2.h #include libssh2_sftp.h class SftpUploader : public QObject { Q_OBJECT public: explicit SftpUploader(QObject *parent nullptr); ~SftpUploader(); // 上传文件到 SFTP 服务器 bool uploadFile(const QString host, int port, const QString username, const QString password, const QString localFilePath, const QString remoteDir); private: // 创建远程目录递归创建多级目录 bool createRemoteDir(LIBSSH2_SFTP *sftp, const QString remoteDir); LIBSSH2_SESSION *m_session; // SSH 会话 QTcpSocket *m_socket; // TCP 连接 }; #endif // SFTP_UPLOADER_HSftpUploader.cpp#include SftpUploader.h #include QFile #include QDebug #include QDir SftpUploader::SftpUploader(QObject *parent) : QObject(parent), m_session(nullptr), m_socket(new QTcpSocket(this)) { // 初始化 libssh2 int rc libssh2_init(0); if (rc ! 0) { qCritical() libssh2 初始化失败: rc; } } SftpUploader::~SftpUploader() { // 清理资源 if (m_session) { libssh2_session_disconnect(m_session, Normal shutdown); libssh2_session_free(m_session); } libssh2_exit(); } bool SftpUploader::createRemoteDir(LIBSSH2_SFTP *sftp, const QString remoteDir) { if (remoteDir.isEmpty() || remoteDir /) return true; // 按 / 分割路径递归创建 QStringList dirs remoteDir.split(/, QString::SkipEmptyParts); QString currentPath; foreach (const QString dir, dirs) { currentPath / dir; // 检查目录是否存在 LIBSSH2_SFTP_HANDLE *handle libssh2_sftp_opendir(sftp, currentPath.toUtf8().constData()); if (handle) { libssh2_sftp_closedir(handle); continue; // 目录已存在继续下一级 } // 目录不存在创建目录权限 0755 int rc libssh2_sftp_mkdir(sftp, currentPath.toUtf8().constData(), 0755); if (rc ! 0) { qCritical() 创建远程目录失败: currentPath 错误码: rc; return false; } } return true; } bool SftpUploader::uploadFile(const QString host, int port, const QString username, const QString password, const QString localFilePath, const QString remoteDir) { // 1. 建立 TCP 连接 m_socket-connectToHost(host, port); if (!m_socket-waitForConnected(5000)) { qCritical() TCP 连接失败: m_socket-errorString(); return false; } // 2. 初始化 SSH 会话 m_session libssh2_session_init(); if (!m_session) { qCritical() SSH 会话初始化失败; m_socket-close(); return false; } // 3. 进行 SSH 握手 int rc libssh2_session_handshake(m_session, m_socket-socketDescriptor()); if (rc ! 0) { qCritical() SSH 握手失败: libssh2_session_last_error(m_session, nullptr, nullptr, 0); libssh2_session_free(m_session); m_session nullptr; m_socket-close(); return false; } // 4. 密码认证 rc libssh2_userauth_password(m_session, username.toUtf8().constData(), password.toUtf8().constData()); if (rc ! 0) { qCritical() SSH 认证失败: libssh2_session_last_error(m_session, nullptr, nullptr, 0); libssh2_session_disconnect(m_session, 认证失败); libssh2_session_free(m_session); m_session nullptr; m_socket-close(); return false; } // 5. 初始化 SFTP 会话 LIBSSH2_SFTP *sftp libssh2_sftp_init(m_session); if (!sftp) { qCritical() SFTP 初始化失败: libssh2_session_last_error(m_session, nullptr, nullptr, 0); libssh2_session_disconnect(m_session, SFTP 初始化失败); libssh2_session_free(m_session); m_session nullptr; m_socket-close(); return false; } // 6. 创建远程目录 if (!createRemoteDir(sftp, remoteDir)) { libssh2_sftp_shutdown(sftp); libssh2_session_disconnect(m_session, 创建目录失败); libssh2_session_free(m_session); m_session nullptr; m_socket-close(); return false; } // 7. 打开本地文件 QFile localFile(localFilePath); if (!localFile.open(QIODevice::ReadOnly)) { qCritical() 打开本地文件失败: localFile.errorString(); libssh2_sftp_shutdown(sftp); libssh2_session_disconnect(m_session, 打开本地文件失败); libssh2_session_free(m_session); m_session nullptr; m_socket-close(); return false; } // 8. 构建远程文件路径 QString fileName QFileInfo(localFile).fileName(); QString remoteFilePath remoteDir / fileName; if (remoteFilePath.startsWith(//)) { remoteFilePath remoteFilePath.mid(1); // 处理路径拼接可能出现的双斜杠 } // 9. 创建远程文件写模式权限 0644 LIBSSH2_SFTP_HANDLE *sftpHandle libssh2_sftp_open(sftp, remoteFilePath.toUtf8().constData(), LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC, 0644); if (!sftpHandle) { qCritical() 创建远程文件失败: remoteFilePath 错误: libssh2_sftp_last_error(sftp); localFile.close(); libssh2_sftp_shutdown(sftp); libssh2_session_disconnect(m_session, 创建远程文件失败); libssh2_session_free(m_session); m_session nullptr; m_socket-close(); return false; } // 10. 上传文件内容 const int BUFFER_SIZE 1024 * 8; char buffer[BUFFER_SIZE]; qint64 bytesRead; bool uploadSuccess true; while ((bytesRead localFile.read(buffer, BUFFER_SIZE)) 0) { // 写入远程文件 ssize_t bytesWritten libssh2_sftp_write(sftpHandle, buffer, bytesRead); if (bytesWritten ! bytesRead) { qCritical() 文件写入失败已写: bytesWritten 需写: bytesRead; uploadSuccess false; break; } } // 11. 清理资源 localFile.close(); libssh2_sftp_close(sftpHandle); libssh2_sftp_shutdown(sftp); libssh2_session_disconnect(m_session, 文件上传完成); libssh2_session_free(m_session); m_session nullptr; m_socket-close(); if (uploadSuccess localFile.error() QFile::NoError) { qInfo() QString::fromLocal8Bit(文件上传成功: ) remoteFilePath; return true; } else { qCritical() QString::fromLocal8Bit(文件上传失败: ) localFile.errorString(); return false; } }main.cpp#include QCoreApplication #includeSftpUploader.h int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 配置服务器信息替换为实际信息 QString host xx.xx.xx.xx; // Linux 服务器 IP int port 22; // SSH 默认端口 QString username root; // 用户名 QString password root; // 密码 QString localFilePath D:/test.py; // 本地文件路径 QString remoteDir /var/www/html/Demonstration.8/public/md; // 远程目录 // 执行上传 SftpUploader uploader; bool success uploader.uploadFile(host, port, username, password, localFilePath, remoteDir); return success ? 0 : 1; }程序运行截图如下