为什么执行HTTPS / SSL请求时,此C ++ ASIO,BEAST服务器会进入错误状态

时间:2019-04-03 15:48:39

标签: c++ ssl https boost-asio boost-beast

我想写一个能回答HTTP请求的服务器。我不在乎HTTPS。如果有人执行HTTPS请求,我想拒绝该请求并继续其他HTTP请求。我的代码如下:

#include <boost/asio.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <thread>
#include <iostream>
using namespace std;

int main(){
    boost::asio::io_context ioc;
    boost::asio::ip::tcp::acceptor acceptor(ioc, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), 8000));
    boost::beast::flat_buffer request_buffer;
    for(;;){
        boost::asio::ip::tcp::socket socket(ioc);
        acceptor.accept(socket);

        boost::beast::http::request<boost::beast::http::string_body> request;
        try{
            boost::beast::http::read(socket, request_buffer, request);
            cout << "OK" << endl;

            boost::beast::http::response<boost::beast::http::string_body> response(boost::beast::http::status::ok, request.version());
            std::string body = "hello";
            response.content_length(body.size());
            response.body() = std::move(body);
            boost::beast::http::write(socket, response);

        }catch(...){
            cout << "BAD" << endl;
        }
        socket.close();
    }
}

我运行代码并使用Firefox按以下顺序执行请求:

  1. http请求
  2. 一个https请求
  3. http请求

我希望获得以下服务器输出:

OK
BAD
OK

但是,我得到的是:

OK
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD

引发的函数为boost::beast::http::read。但是,我不明白为什么。在两次调用之间,我创建了一个新的套接字对象,因此我的理解是第二个请求的结果不应影响第三个请求。但是,显然我的理解是不正确的。有人可以解释我对ASIO和/或BEAST如何工作的理解是错误的。谢谢:)

1 个答案:

答案 0 :(得分:1)

HTTPS是基于SSL流的HTTP。 SSL流是通过常规TCP套接字实现的。 Beast抛出“ Read”,因为它没有看到HTTP请求,只是看到了看起来像随机二进制数据的东西。它不知道(也不会检测到它是SSL流)。

看到很多“ BAD”行的原因是因为Firefox看到TLS流试图连接然后失败。只是重试SSL流连接。因此,您将最终获得多条BAD连接线。

这就是为什么默认的HTTP端口为80,默认的HTTPS端口为443的原因。与HTTP服务器的HTTPS客户端连接将永远无法工作,并且会产生您看到的结果类型。

更新: 之所以进入BAD循环,是因为request_buffer不会在错误时清除,因此它包含第一个SSL数据连接,每次从新套接字读取数据时,该数据都会不断添加到该数据。

最简单的解决方法是将request_buffer的定义移动到与请求对象相同的位置。或者,您可以consume未处理的数据然后再循环。