平台Windows
-
重点声明
boost中的asio库,并不是编译出来的,而是模板编译的。你在stage/lib/cmake中是找不到的,asio的包的。
asio的ssl支持,使用的是OpenSSL库,因此,需要自己安装OpenSSL库,才能使用。安装OpenSSL之后,仍然需要在项目中引入OpenSSL库,否则会出现头文件、未定义的等等一系列错误。如果你是在windows下,我建议你使用OpenSSL的静态库链接,这样比较简单。下面是代码示例。还有一点,windows的OpenSSL会使用windows的库,所以需要链接#pragma comment(lib, "Crypt32.lib")
-
代码示例
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(boost-test LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 设置boost搜索路径前缀
set(CMAKE_PREFIX_PATH "D:/library/boost_1_76_0/stage/lib/cmake")
find_package(Boost REQUIRED COMPONENTS json)
add_executable(boost-test main.cpp SslClient.cpp)
# 设置ssl库路径
set(ssl_path "C:/Program Files/OpenSSL-Win64/lib/VC/static/")
# 如果找到boost json库的操作
if (Boost_FOUND)
# 设置头文件,并且链接boost json库以及OpenSSL的静态库
include_directories(${Boost_INCLUDE_DIRS} "C:/Program Files/OpenSSL-Win64/include")
target_link_libraries(${PROJECT_NAME} Boost::json ${ssl_path}libssl64MT.lib ${ssl_path}libcrypto64MT.lib)
endif()
SslClient.h
#ifndef SSLCLIENT_H
#define SSLCLIENT_H
#include <boost/noncopyable.hpp>
#include <boost/json.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/asio/ssl/stream_base.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
class SslClient : public boost::noncopyable
{
public:
using TcpSocketType = boost::asio::ip::tcp::socket;
using SslSocketType = boost::asio::ssl::stream<TcpSocketType>;
explicit SslClient(boost::asio::io_context& io) noexcept;
void start();
void handleRead(const boost::system::error_code& error, std::size_t num) noexcept;
std::string domain; // 域名
private:
char _buffer[2048];
boost::asio::io_context& _io;
boost::asio::ssl::context _ctx; // ssl 上下文协议
SslSocketType _stream; // ssl - tcp 流,需要注意的是,该对象内部成员就是 tcp-socket
};
#endif // SSLCLIENT_H
SSLClient.cpp
#include "sslclient.h"
#include <iostream>
// 初始化,设置ssl上下文以及ssl-stream
SslClient::SslClient(boost::asio::io_context& io) noexcept
: _io(io), _ctx(boost::asio::ssl::context::sslv23), _stream(io, _ctx) {}
void SslClient::start() {
// 解析域名拿到ip地址
boost::asio::ip::tcp::resolver resolver(_io);
boost::asio::ip::tcp::resolver::query query(domain, boost::lexical_cast<std::string>(443));
auto begin = resolver.resolve(query);
boost::asio::ip::tcp::resolver::iterator end;
if (begin == end)
return;
// 获取底层的tcp套接字,先链接tcp
_stream.lowest_layer().connect(begin->endpoint());
// 进行ssl握手
_stream.handshake(SslSocketType::handshake_type::client);
const char* strHeader =
"GET / HTTP/1.1\r\n"
"Host: www.baidu.com\r\n"
"Connection: keep-alive\r\n"
"\r\n";
// 发送请求头
_stream.write_some(boost::asio::const_buffer(strHeader, std::strlen(strHeader)));
// ssl 进行读取
_stream.async_read_some(boost::asio::buffer(_buffer, sizeof(_buffer)),
std::bind(&SslClient::handleRead, this,
std::placeholders::_1,
std::placeholders::_2)
);
}
void SslClient::handleRead(const boost::system::error_code& error, std::size_t num) noexcept {
try {
if (error) {
if (num == 0) {
_stream.shutdown();
_stream.lowest_layer().close();
}
return;
}
_buffer[num] = '\0';
std::cout << _buffer;
// 继续监听异步读取
_stream.async_read_some(boost::asio::buffer(_buffer, sizeof(_buffer)),
std::bind(&SslClient::handleRead, this,
std::placeholders::_1,
std::placeholders::_2)
);
} catch(const std::exception&) {
}
}
main.cpp
#include <iostream>
#include <boost/lexical_cast.hpp>
#include "sslclient.h"
// 因为OpenSSL会使用win32底层的库,所以一定要链接这个库,否会出现未定义的错误
#pragma comment(lib, "Crypt32.lib")
int main(int, char**)
{
std::cout << "hello asio\n";
boost::asio::io_context io;
SslClient app(io);
app.domain = "www.baidu.com";
app.start();
io.run();
}
版权声明:本文为BCMY0110原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。