boost::asio ssl
以 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
client.cpp
#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; }總結
以上是生活随笔為你收集整理的boost::asio ssl的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: boost ref, bind
- 下一篇: 服务端统一时间戳 boost::date