boost::asio ssl

78 篇文章 2 订阅

以 boost::asio::ssl::stream<boost::asio::ip::tcp::socket>  代替 boost::asio::ip::tcp::socket

客户端connect成功之后, 需要socket().async_handshake(); 成功之后才能发起异步读写。

服务端accept成功之后, 需要socket().async_handshake(); 成功之后才能发起异步读写。

g++ -o server server.cpp -lboost_system-mt -lboost_filesystem-mt -lpthread -lssl

g++ -o client client.cpp -lboost_system-mt -lboost_filesystem-mt -lpthread -lssl


简单的echo server

./server 9999

./client 0.0.0.0 9999 发送消息后服务端将发回。


与tcp socket相比, 多一个handshake过程。 

数据的封包与解析与tcp完全一致。 屏蔽了ssl协议的数据。


client.cpp && server.cpp  from doc/html/boost_asio/example/ssl   boost自带的例子

server.pem && ca.pem && dh512.pem from https://github.com/microcai/netserver/tree/master/netserver


#include <cstdlib>  
#include <iostream>  
#include <boost/bind.hpp>  
#include <boost/asio.hpp>  
#include <boost/asio/ssl.hpp>  
  
enum { max_length = 1024 };  
  
class client  
{  
public:  
  client(boost::asio::io_service& io_service,  
      boost::asio::ssl::context& context,  
      boost::asio::ip::tcp::resolver::iterator endpoint_iterator)  
    : socket_(io_service, context)  
  {  
    socket_.set_verify_mode(boost::asio::ssl::verify_peer);  
    socket_.set_verify_callback(  
        boost::bind(&client::verify_certificate, this, _1, _2));  
  
    boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,  
        boost::bind(&client::handle_connect, this,  
          boost::asio::placeholders::error));  
  }  
  
  bool verify_certificate(bool preverified,  
      boost::asio::ssl::verify_context& ctx)  
  {  
    // The verify callback can be used to check whether the certificate that is  
    // being presented is valid for the peer. For example, RFC 2818 describes  
    // the steps involved in doing this for HTTPS. Consult the OpenSSL  
    // documentation for more details. Note that the callback is called once  
    // for each certificate in the certificate chain, starting from the root  
    // certificate authority.  
  
    // In this example we will simply print the certificate's subject name.  
    char subject_name[256];  
    X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());  
    X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);  
    std::cout << "Verifying " << subject_name << "\n";  
  
    return preverified;  
  }  
  
  void handle_connect(const boost::system::error_code& error)  
  {  
    if (!error)  
    {  
      socket_.async_handshake(boost::asio::ssl::stream_base::client,  
          boost::bind(&client::handle_handshake, this,  
            boost::asio::placeholders::error));  
    }  
    else  
    {  
      std::cout << "Connect failed: " << error.message() << "\n";  
    }  
  }  
  
  void handle_handshake(const boost::system::error_code& error)  
  {  
    if (!error)  
    {  
      std::cout << "Enter message: ";  
      std::cin.getline(request_, max_length);  
      size_t request_length = strlen(request_);  
  
      boost::asio::async_write(socket_,  
          boost::asio::buffer(request_, request_length),  
          boost::bind(&client::handle_write, this,  
            boost::asio::placeholders::error,  
            boost::asio::placeholders::bytes_transferred));  
    }  
    else  
    {  
      std::cout << "Handshake failed: " << error.message() << "\n";  
    }  
  }  
  
  void handle_write(const boost::system::error_code& error,  
      size_t bytes_transferred)  
  {  
    if (!error)  
    {  
      boost::asio::async_read(socket_,  
          boost::asio::buffer(reply_, bytes_transferred),  
          boost::bind(&client::handle_read, this,  
            boost::asio::placeholders::error,  
            boost::asio::placeholders::bytes_transferred));  
    }  
    else  
    {  
      std::cout << "Write failed: " << error.message() << "\n";  
    }  
  }  
  
  void handle_read(const boost::system::error_code& error,  
      size_t bytes_transferred)  
  {  
    if (!error)  
    {  
      std::cout << "Reply: ";  
      std::cout.write(reply_, bytes_transferred);  
      std::cout << "\n";  
    }  
    else  
    {  
      std::cout << "Read failed: " << error.message() << "\n";  
    }  
  }  
  
private:  
  boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;  
  char request_[max_length];  
  char reply_[max_length];  
};  
  
int main(int argc, char* argv[])  
{  
  try  
  {  
    if (argc != 3)  
    {  
      std::cerr << "Usage: client <host> <port>\n";  
      return 1;  
    }  
  
    boost::asio::io_service io_service;  
  
    boost::asio::ip::tcp::resolver resolver(io_service);  
    boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]);  
    boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);  
  
    boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);  
    ctx.load_verify_file("ca.pem");  
  
    client c(io_service, ctx, iterator);  
  
    io_service.run();  
   }  
  catch (std::exception& e)  
  {  
    std::cerr << "Exception: " << e.what() << "\n";  
  }  
  
  return 0;  
}  

server.cpp

#include <cstdlib>  
#include <iostream>  
#include <string>  
#include <boost/bind.hpp>  
#include <boost/asio.hpp>  
#include <boost/asio/ssl.hpp>  
  
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;  
  
class session  
{  
public:  
  session(boost::asio::io_service& io_service,  
      boost::asio::ssl::context& context)  
    : socket_(io_service, context)  
  {  
  }  
  
  ssl_socket::lowest_layer_type& socket()  
  {  
    return socket_.lowest_layer();  
  }  
  
  void start()  
  {  
    socket_.async_handshake(boost::asio::ssl::stream_base::server,  
        boost::bind(&session::handle_handshake, this,  
          boost::asio::placeholders::error));  
  }  
  
  void handle_handshake(const boost::system::error_code& error)  
  {  
    if (!error)  
    {  
      socket_.async_read_some(boost::asio::buffer(data_, max_length),  
          boost::bind(&session::handle_read, this,  
            boost::asio::placeholders::error,  
            boost::asio::placeholders::bytes_transferred));  
    }  
    else  
    {  
      delete this;  
    }  
  }  
  
  void handle_read(const boost::system::error_code& error,  
      size_t bytes_transferred)  
  {  
     if (!error)  
    {  
        std::cout <<"read: " << std::string(data_, bytes_transferred) << std::endl;  
      boost::asio::async_write(socket_,  
          boost::asio::buffer(data_, bytes_transferred),  
          boost::bind(&session::handle_write, this,  
            boost::asio::placeholders::error));  
    }  
    else  
    {  
      delete this;  
    }  
  }  
  
  void handle_write(const boost::system::error_code& error)  
  {  
    if (!error)  
    {  
      socket_.async_read_some(boost::asio::buffer(data_, max_length),  
          boost::bind(&session::handle_read, this,  
            boost::asio::placeholders::error,  
            boost::asio::placeholders::bytes_transferred));  
    }  
    else  
    {  
      delete this;  
    }  
  }  
  
private:  
  ssl_socket socket_;  
  enum { max_length = 1024 };  
  char data_[max_length];  
};  
  
class server  
{  
public:  
  server(boost::asio::io_service& io_service, unsigned short port)  
    : io_service_(io_service),  
      acceptor_(io_service,  
          boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),  
      context_(boost::asio::ssl::context::sslv23)  
  {  
    context_.set_options(  
        boost::asio::ssl::context::default_workarounds  
        | boost::asio::ssl::context::no_sslv2  
        | boost::asio::ssl::context::single_dh_use);  
    context_.set_password_callback(boost::bind(&server::get_password, this));  
    context_.use_certificate_chain_file("server.pem");  
    context_.use_private_key_file("server.pem", boost::asio::ssl::context::pem);  
    context_.use_tmp_dh_file("dh512.pem");  
  
    start_accept();  
  }  
  
  std::string get_password() const  
  {  
    return "test";  
  }  
  
  void start_accept()  
  {  
    session* new_session = new session(io_service_, context_);  
    acceptor_.async_accept(new_session->socket(),  
        boost::bind(&server::handle_accept, this, new_session,  
          boost::asio::placeholders::error));  
  }  
  
  void handle_accept(session* new_session,  
      const boost::system::error_code& error)  
  {  
    if (!error)  
    {  
      new_session->start();  
    }  
    else  
    {  
      delete new_session;  
    }  
  
    start_accept();  
  }  
  
private:  
  boost::asio::io_service& io_service_;  
  boost::asio::ip::tcp::acceptor acceptor_;  
  boost::asio::ssl::context context_;  
};  
  
int main(int argc, char* argv[])  
{  
  try  
  {  
    if (argc != 2)  
    {  
      std::cerr << "Usage: server <port>\n";  
      return 1;  
    }  
  
    boost::asio::io_service io_service;  
  
    using namespace std; // For atoi.  
    server s(io_service, atoi(argv[1]));  
  
    io_service.run();  
  }  
  catch (std::exception& e)  
  {  
    std::cerr << "Exception: " << e.what() << "\n";  
  }  
  
  return 0;  
}  

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`boost::asio::ssl::context`是Boost.Asio库中的一个类,用于处理SSL/TLS(Secure Sockets Layer/Transport Layer Security)通信。它提供了高级的接口,以便在Asio网络编程中设置和管理SSL连接。`context`类包含了多种选项,用于配置SSL上下文,确保安全的通信。以下是一些关键的选项: 1. **mode**: 设置SSL模式,例如`boost::asio::ssl::context::client`(客户端)或`boost::asio::ssl::context::server`(服务器)。 2. **cipher_list**: 可以指定允许使用的加密算法列表,如"TLSv1+AES256+SHA256"。 3. **protocol_version**: 设置支持的SSL/TLS协议版本,如`tlsv1_2`、`tlsv1_3`。 4. **cert_chain**: 加载服务器证书,通常包括私钥,确保身份验证。 5. **private_key**: 加载用于加密的私钥。 6. **trust_store**: 信任存储,包含CA(证书颁发机构)证书,用于验证对方的证书。 7. **options**: 可以调整其他选项,如允许匿名身份、要求服务器证明等。 8. **alpn_negotiation**: 设置Application-Layer Protocol Negotiation (ALPN)支持,用于选择客户端支持的协议。 9. **session_cache**: 控制SSL会话缓存,可以优化性能。 10. **verify_mode**: 客户端验证服务器的方式,如`verify_none`、`verify_peer`、`verify_client_once`等。 11. **next_protocols**: 服务器上如何处理ALPN协商,可能是一个字符串列表。 每个选项都有其特定的意义和用法,使用时需根据实际需求进行配置。如果你对某个选项的具体用法有疑问,可以告诉我,我会进一步解释。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值