Boost-SSL-socket使用记录

  • Post author:
  • Post category:其他




平台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 版权协议,转载请附上原文出处链接和本声明。