我想写一个能回答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按以下顺序执行请求:
我希望获得以下服务器输出:
OK
BAD
OK
但是,我得到的是:
OK
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
引发的函数为boost::beast::http::read
。但是,我不明白为什么。在两次调用之间,我创建了一个新的套接字对象,因此我的理解是第二个请求的结果不应影响第三个请求。但是,显然我的理解是不正确的。有人可以解释我对ASIO和/或BEAST如何工作的理解是错误的。谢谢:)
答案 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未处理的数据然后再循环。