Boost.Beast
介绍
Beast是header-only的C++库,通过使用Boost.Asio
一致的异步模型提供底层HTTP/1,WebSocket
和网络协议的术语和算法,可作为编写通用网络库的基础库。
该库设计用于:
- 对称性:算法与角色无关;构建客户端和/或服务器。
- 易于使用:
Boost.Asio
用户将立即了解如何使用Beast。 - 灵活性:用户可以做出重要的决定,例如缓冲区或线程管理。
- 性能:构建处理数千个或更多连接的应用程序。
- 进一步抽象的基础。组件非常适合在其上进行构建。
该库不是客户端或服务器,但是可以用来构建这些东西。提供了许多示例,包括客户端和服务器,它们可以用作编写您自己的程序的起点。
动机
Beast允许用户使用HTTP/1和WebSocket
创建自己的库,客户端和服务器。因为Beast会处理底层协议的详细信息,所以代码将更易于实现,理解和维护。 HTTP和WebSocket
协议驱动了大多数万维网。每个Web浏览器都实现这些协议以加载网页并允许客户端程序(通常以JavaScript编写)进行交互通信。C++得益于这些协议的标准化实现。
要求
重要 : 该库供熟悉Boost.Asio的程序员使用。希望使用异步接口的用户应该已经知道如何使用回调或协程创建并发网络程序。
Beast要求:
- C++11:对大多数语言功能的强大支持。
Boost
:Beast仅适用于Boost,不适用于独立的Asio
OpenSSL
:生成测试,示例以及使用TLS/Secure
套接字是必需的。
源码只有头文件。除以下情况外,通常不需要在程序的链接步骤中添加其他库以使用Beast:
- 使用通过调用
boost::asio::spawn
创建的协程时,需要将Boost.Coroutine
库添加到程序中。 - 使用
boost::asio::ssl::stream
时,您需要将OpenSSL
库添加到程序中。
请访问Boost文档以获取有关如何为特定环境系统构建和链接Boost库的说明。
快速浏览
这些完整的程序旨在使读者快速印象深刻。 它们的源代码和构建脚本位于example目录中。
简单的HTTP客户端
使用HTTP向网站发出GET请求并打印响应:
//HttpSyncClient.cpp
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
namespace beast = boost::beast;
namespace http = beast::http;
using tcp = boost::asio::ip::tcp;
// Performs an HTTP GET and prints the response
int HttpSyncClient(int argc, char **argv) {
try {
auto const host = "www.baidu.com";
auto const port = "80";
auto const target = "/";
int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
// The io_context is required for all I/O
boost::asio::io_context io_context;
// These objects perform our I/O
tcp::resolver resolver(io_context);
beast::tcp_stream stream(io_context);
// Look up the domain name
auto const results = resolver.resolve(host, port);
// Make the connection on the IP address we get from a lookup
stream.connect(results);
// Set up an HTTP GET request message
http::request<http::string_body> req{http::verb::get, target, version};
req.set(http::field::host, host);
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
// Send the HTTP request to the remote host
http::write(stream, req);
// This buffer is used for reading and must be persisted
beast::flat_buffer buffer;
// Declare a container to hold the response
http::response<http::dynamic_body> res;
// Receive the HTTP response
http::read(stream, buffer, res);
// Write the message to standard out
std::cout << res << std::endl;
// Gracefully close the socket
beast::error_code ec;
stream.socket().shutdown(tcp::socket::shutdown_both, ec);
// not_connected happens sometimes
// so don't bother reporting it.
//
if (ec && ec != beast::errc::not_connected)
throw beast::system_error{ec};
// If we get here then the connection is closed gracefully
} catch (std::exception const &e) {
std::cerr << "Error: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
简单的WebSocket客户端
建立WebSocket连接,发送消息并接收回复:
//WebsocketSyncClient.cpp
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
namespace beast = boost::beast; // from <boost/beast.hpp>
namespace http = beast::http; // from <boost/beast/http.hpp>
namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
namespace net = boost::asio; // from <boost/asio.hpp>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
// Sends a WebSocket message and prints the response
int WebsocketSyncClient(int /*argc*/, char ** /*argv*/) {
try {
auto const host = "127.0.0.1";
auto const port = "8080";
auto const text = "Hello World!1111";
// The io_context is required for all I/O
net::io_context ioc;
// These objects perform our I/O
tcp::resolver resolver{ioc};
websocket::stream<tcp::socket> ws{ioc};
// Look up the domain name
auto const results = resolver.resolve(host, port);
// Make the connection on the IP address we get from a lookup
net::connect(ws.next_layer(), results.begin(), results.end());
// Set a decorator to change the User-Agent of the handshake
ws.set_option(websocket::stream_base::decorator([](websocket::request_type &req) {
req.set(http::field::user_agent,
std::string(BOOST_BEAST_VERSION_STRING) + " websocket-client-coro");
}));
// Perform the websocket handshake
ws.handshake(host, "/");
// Send the message
ws.write(net::buffer(std::string(text)));
// This buffer will hold the incoming message
beast::flat_buffer buffer;
// Read a message into our buffer
ws.read(buffer);
// Close the WebSocket connection
ws.close(websocket::close_code::normal);
// If we get here then the connection is closed gracefully
// The make_printable() function helps print a ConstBufferSequence
std::cout << beast::make_printable(buffer.data()) << std::endl;
} catch (std::exception const &e) {
std::cerr << "Error: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
安全审查(Bishop Fox)
自2005年以来,毕晓普·福克斯(Bishop Fox)为全球财富1000强,高科技初创企业和金融机构提供了安全咨询服务。 Beast与Bishop Fox合作,评估了Boost C++ Beast HTTP/S网络库的安全性。以下报告详细介绍了从2017年9月11日开始的参与过程中发现的发现。
评估团队对Beast库进行了混合应用评估。 Bishop Fox的混合应用程序评估方法利用了应用程序渗透测试的实际攻击技术,结合有针对性的源代码审查,以彻底识别应用程序安全漏洞。这些全面知识评估始于对已部署的应用程序和源代码的自动扫描。接下来,将扫描结果的分析与手动检查结合起来,以彻底识别潜在的应用程序安全漏洞。此外,该团队还对应用程序体系结构和业务逻辑进行了审查,以查找所有设计级别的问题。最后,团队对这些问题进行手动开发和审查,以验证结果。