使用libssh2.1.10内存大量激增。考虑使用libssh。如果没有遇到什么问题,更新整个使用过程。

文章讲述了在使用libssh2.1.10过程中遇到的内存激增问题,作者通过实例展示了如何构建一个C++SFTPClient并解决内存泄漏,同时提到了考虑转向更易用的libssh库作为替代。
摘要由CSDN通过智能技术生成

使用libssh2.1.10这段代码内存大量激增(已解决),不知道时什么问题,考虑使用libssh。
libssh使用难度比较高,可以直接使用openssl


#libssh 项目构建
cmake -G "Visual Studio 14 2015" -DBUILD_SHARED_LIBS=ON -DWITH_MBEDTLS=OFF -DWITH_GCRYPT=OFF -DCMAKE_INSTALL_PREFIX=E:\devlibs\libs/libssh -DCMAKE_GENERATOR_TOOLSET="v140_xp"  -DOPENSSL_ROOT_DIR=E:\devlibs\libs\openssl -DOPENSSL_CRYPTO_LIBRARY=E:\devlibs\libs\openssl\lib -DZLIB_LIBRARY=E:\devlibs\libs\zlib\lib -DZLIB_INCLUDE_DIR=E:\devlibs\libs\zlib\include ..
//libssh2 内存泄漏代码,清楚的大神,请指教。
//20240314已经解决
#include <libssh2.h>
#include <libssh2_sftp.h>

#include <iostream>
#include <cstring>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>






class SFTPClient {
public:
    SFTPClient(const std::string &hostname, int port, const std::string &username, const std::string &password)
        : hostname(hostname), port(port), username(username), password(password), sock(INVALID_SOCKET), session(nullptr), sftp_session(nullptr) {
    }

    ~SFTPClient() {
        disconnect();
    }

    bool WaitConnect()
    {
        struct timeval tv;
        tv.tv_sec = 10;
        tv.tv_usec = 0;

        fd_set write, err;
        FD_ZERO(&write);
        FD_ZERO(&err);
        FD_SET(sock, &write);
        FD_SET(sock, &err);

        // check if the socket is ready

        int rc = select(sock + 1, NULL, &write, &err, &tv);

        switch (rc)
        {
        case 0:
            std::cout << ("connect server timeout");
        case -1:
            std::cout << ("connect server select (%d)", errno);
        default:
            break;
        }

        if (!FD_ISSET(sock, &write))
        {
            std::cout << ("select write socket failed: %d", errno);
        }
        int error = WSAEINPROGRESS;
        int len = sizeof(int);
        getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*)(&error), (socklen_t*)&len);
        if (error)
        {
            std::cout << ("connect WSAEINPROGRESS getsockopt[SO_ERROR] : %d");
        }
        return true;
    }

    bool connect() {



        // 创建socket
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock == INVALID_SOCKET) {
            std::cerr << "Failed to create socket" << std::endl;
            return false;
        }

        // 设置socket为非阻塞模式
        u_long mode = 1; // 非阻塞模式
        if (ioctlsocket(sock, FIONBIO, &mode) != NO_ERROR) {
            std::cerr << "Failed to set socket non-blocking" << std::endl;
            return false;
        }

        sockaddr_in sin{};
        sin.sin_family = AF_INET;
        sin.sin_port = htons(port);
        inet_pton(AF_INET, hostname.c_str(), &sin.sin_addr);

        // 非阻塞connect
        if (::connect(sock, (sockaddr*)(&sin), sizeof(sin)) == SOCKET_ERROR) {
            if (WSAGetLastError() != WSAEWOULDBLOCK) {
                std::cerr << "Failed to connect" << std::endl;
                return false;
            }
            WaitConnect();
        }

        // 创建一个SSH会话
        session = libssh2_session_init();
        if (!session) {
            std::cerr << "Failed to create libssh2 session" << std::endl;
            return false;
        }

        libssh2_session_set_blocking(session, 0); // 设置session为非阻塞模式

                                                  // 进行SSH会话的握手
        int rc;
        do {
            rc = libssh2_session_handshake(session, sock);
        } while (rc == LIBSSH2_ERROR_EAGAIN);
        if (rc) {
            std::cerr << "Failure establishing SSH session: " << rc << std::endl;
            return false;
        }

        // 用户认证
        do {
            rc = libssh2_userauth_password(session, username.c_str(), password.c_str());
        } while (rc == LIBSSH2_ERROR_EAGAIN);
        if (rc) {
            std::cerr << "Authentication by password failed." << std::endl;
            return false;
        }

        // 初始化SFTP会话
        do {
            sftp_session = libssh2_sftp_init(session);
        } while (!sftp_session && libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN);
        if (!sftp_session) {
            std::cerr << "Unable to init SFTP session" << std::endl;
            return false;
        }

        return true;
    }

    void disconnect() {
        if (sftp_session) {
            libssh2_sftp_shutdown(sftp_session); //这里需要采用无阻塞模式释放。才能解决内存泄漏问题
            sftp_session = nullptr;
        }
        if (session) {
            libssh2_session_disconnect(session, "Normal Shutdown");
            libssh2_session_free(session);
            session = nullptr;
        }
        if (sock != INVALID_SOCKET) {
            closesocket(sock);
            sock = INVALID_SOCKET;
        }
        //libssh2_exit();
        //WSACleanup();
    }

private:
    std::string hostname;
    int port;
    std::string username;
    std::string password;

    SOCKET sock;
    LIBSSH2_SESSION *session;
    LIBSSH2_SFTP *sftp_session;
};
#include <memory> 
void test_once_memory()
{
    std::unique_ptr<SFTPClient> client = std::make_unique<SFTPClient>("192.168.2.121", 22, "abc", "123456");
    if (client->connect()) {
        std::cout << "Connected successfully" << std::endl;
        // 这里可以添加更多的SFTP操作,例如上传、下载文件等
    }
    else {
        std::cerr << "Failed to connect" << std::endl;
    }
}


int main() {

#ifdef WIN32
    WSADATA wsadata;
    int err;

    err = WSAStartup(MAKEWORD(2, 0), &wsadata);
    if (err != 0) {
        fprintf(stderr, "WSAStartup failed with error: %d\n", err);
        return 1;
    }
#endif
    // 初始化libssh2
    if (libssh2_init(0) != 0) {
        std::cerr << "libssh2 initialization failed" << std::endl;
        return false;
    }
    test_once_memory();

    WSACleanup();
    return 0;
}

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值