CryptoPP:如何使用 SocketSource 和 SocketSink

Posted

技术标签:

【中文标题】CryptoPP:如何使用 SocketSource 和 SocketSink【英文标题】:CryptoPP: how to use SocketSource and SocketSink 【发布时间】:2014-06-23 11:05:13 【问题描述】:

我正在尝试通过 SocketSource 和 SocketSink 发送字符串。但不知何故,它不能正常工作。我只是想将它从我的服务器发送到客户端。代码如下:

服务器:

    CryptoPP::Socket server;
    CryptoPP::Socket client;
    sockaddr_in client_sadr;
    CryptoPP::socklen_t size_sock = sizeof(sockaddr_in);
    timeval timev = 3, 0;
    std::string test("a simple test");

    CryptoPP::Socket::StartSockets();

    server.Create(SOCK_STREAM);
    server.Bind(4213, NULL);
    server.Listen();

    server.Accept(client, (sockaddr*)&client_sadr, &size_sock);

    std::cout << "Client connected" << std::endl;

    while (!client.SendReady(&timev));
    CryptoPP::StringSource ss(test, true, new CryptoPP::SocketSink(client));

    std::cout << "Data sent" << std::endl;

    std::cin.ignore();

    client.CloseSocket();
    server.CloseSocket();

    CryptoPP::Socket::ShutdownSockets();

客户:

    CryptoPP::Socket client;
    CryptoPP::socklen_t size_sock = sizeof(sockaddr_in);
    timeval timev = 3, 0;
    std::string test;

    Socket::StartSockets();

    client.Create(SOCK_STREAM);
    client.Connect("127.0.0.1", 4213);

    std::cout << "connected" << std::endl;

    while (!client.ReceiveReady(&timev));
    CryptoPP::SocketSource(client, true, new StringSink(test));

    std::cout << test << std::endl;

    std::cin.ignore();

    client.CloseSocket();
    Socket::ShutdownSockets();

现在发生的情况:连接如愿建立,服务器发送数据,客户端接收数据并在 cin.ignore() 处等待。但是服务器在发送时似乎挂断了,因为它不会打印“数据发送”。它仅在客户端关闭连接时执行此操作。 我现在的问题是,我是不是做错了什么,或者这只是 SocketSource 和 SocketSink 的正常行为,我每次都必须重新连接......

感谢您的帮助:)

【问题讨论】:

【参考方案1】:

以下来自test.cpp。它可能会给你一些想法。我不记得阅读过如何使用它们(而且我从未在程序中使用过它们)。这是我见过PumpAll2 并且使用非阻塞的唯一地方。

您可能会发现它们在 Windows 上比在 Linux 上运行得更好。

void ForwardTcpPort(const char *sourcePortName, const char *destinationHost,
        const char *destinationPortName)

    SocketsInitializer sockInit;

    Socket sockListen, sockSource, sockDestination;

    int sourcePort = Socket::PortNameToNumber(sourcePortName);
    int destinationPort = Socket::PortNameToNumber(destinationPortName);

    sockListen.Create();
    sockListen.Bind(sourcePort);
    setsockopt(sockListen, IPPROTO_TCP, TCP_NODELAY, "\x01", 1);

    cout << "Listing on port " << sourcePort << ".\n";
    sockListen.Listen();

    sockListen.Accept(sockSource);
    cout << "Connection accepted on port " << sourcePort << ".\n";
    sockListen.CloseSocket();

    cout << "Making connection to " << destinationHost << ", port " << destinationPort << ".\n";
    sockDestination.Create();
    sockDestination.Connect(destinationHost, destinationPort);

    cout << "Connection made to " << destinationHost << ", starting to forward.\n";

    SocketSource out(sockSource, false, new SocketSink(sockDestination));
    SocketSource in(sockDestination, false, new SocketSink(sockSource));

    WaitObjectContainer waitObjects;

    while (!(in.SourceExhausted() && out.SourceExhausted()))
    
        waitObjects.Clear();

        out.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - out", NULL));
        in.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - in", NULL));

        waitObjects.Wait(INFINITE_TIME);

        if (!out.SourceExhausted())
        
            cout << "o" << flush;
            out.PumpAll2(false);
            if (out.SourceExhausted())
                cout << "EOF received on source socket.\n";
        

        if (!in.SourceExhausted())
        
            cout << "i" << flush;
            in.PumpAll2(false);
            if (in.SourceExhausted())
                cout << "EOF received on destination socket.\n";
        
    

【讨论】:

谢谢你,它帮助我解决了另一个问题,但如果我试图将字符串连接到套接字它仍然无法工作......

以上是关于CryptoPP:如何使用 SocketSource 和 SocketSink的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用 CryptoPP 解密流后执行 unpadding

CryptoPP 使用方法

我需要在 Qt 中使用 CryptoPP DLL 吗?

如何从 Crypto++ ECDSA 中的签名体中获取签名长度

由cryptopp创建的DER编码公钥与openssl不同

cryptopp 加密库的安装