如何使用OpenSSL读取超过16'384字节的数据?

问题描述 投票:0回答:1

我正在尝试使用 OpenSSL 库用 C++ 编写 HTTPS Web 服务器。

我从 OpenSSL 网站上的简单 TLS 服务器示例开始,但我无法弄清楚如何读取超过 16'384 字节的数据。

所有代码与简单 TLS 服务器示例中的相同,这是我读取数据的部分:

if (SSL_accept(ssl) <= 0) {
    ERR_print_errors_fp(stderr);
} else {
    while (true) {
        char buffer[16'384];
        const auto bytes = SSL_read(ssl, buffer, 16'384);

        const auto ssl_error = SSL_get_error(ssl, bytes);
        const auto pending = SSL_pending(ssl);

        std::cout << bytes << std::endl; // This is always 16'384 when the requests exceeds 16 kB
        std::cout << ssl_error << std::endl; // This is always 0 (SSL_ERROR_NONE)
        std::cout << pending << std::endl; // This is always 0 since we read a full record of data and there's no more pending data in the record
        // How to know if there is more data to read?

        if (ssl_error == SSL_ERROR_NONE && pending == 0) {
            // This condition will always be true (see previous comments)
            break;
        }
    }

    const auto response = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World!";
    SSL_write(ssl, response, strlen(response));
}

我正在使用 Postman 或 Firefox 发出请求来测试这一点,在这两种情况下,退出循环的条件都是 true,即使请求是否超过 16kB。

读取完整记录后,我想知道是否还有另一条记录可以使用循环读取请求的其余部分。

正如我的代码中的注释所暗示的,我做了一些研究:

  • 特别是这个评论详细解释了如何正确阅读请求,我在其他官方示例中看到过。

  • 我也尝试过使套接字异步,但 SSL_read 似乎保持同步。

  • 我遇到过这个例子,这似乎是 BIO 的一个非常简单的用法,但我也没有设法让它工作。

  • 当然,我也看过这篇文章,它让我明白了为什么我无法阅读超过 16 kB,但没有真正解决问题。

使用 BIO 是正确的方法吗?如果是这样,怎么办?我不太懂BIO。 或者有没有不使用BIO的解决方案?

c++ c sockets ssl openssl
1个回答
0
投票

SSL_pending
仅表示 SSL 对象内部是否有更多数据缓冲。它没有提及操作系统套接字缓冲区中缓冲的数据、仍在传输中的数据或发送方尚未传输的数据。

因此,不要依赖

SSL_pending

 作为退出循环的条件。相反,请再次拨打 
SSL_read
。仅当返回等于或小于 0 时,SSL 会话内就没有更多内容可供读取。

© www.soinside.com 2019 - 2024. All rights reserved.