C++ 使用Boost:ASIO和ASIO SSL示例代码通过TLS发送数据

C++ 使用Boost:ASIO和ASIO SSL示例代码通过TLS发送数据,c++,boost,boost-asio,C++,Boost,Boost Asio,目前我正在研究使用Boost ASIO发送数据。我知道io\u服务是底层依赖操作系统的io功能的抽象,调用run()将轮询asio队列中所有未完成的句柄,并在之后完成 但是看看asio的SSL示例(代码见下文),我不知道如何在客户端的正常“工作流程”之外保持连接(或会话,或其他)打开并通过此连接读写数据 这意味着:如果我在handle\u handshake中调用客户端的send()方法,消息就被发送了。但是,如果我尝试从主方法调用c.send(),则在客户端握手成功后,什么也不会发生 为什么在

目前我正在研究使用Boost ASIO发送数据。我知道
io\u服务
是底层依赖操作系统的io功能的抽象,调用
run()
将轮询asio队列中所有未完成的句柄,并在之后完成

但是看看asio的SSL示例(代码见下文),我不知道如何在客户端的正常“工作流程”之外保持连接(或会话,或其他)打开并通过此连接读写数据

这意味着:如果我在
handle\u handshake
中调用客户端的
send()
方法,消息就被发送了。但是,如果我尝试从主方法调用
c.send()
,则在
客户端握手成功后,什么也不会发生

为什么在所描述的场景中处理的
send()
不同?
io\u服务是否已完成

注意:请不要担心下面的代码量。这是ASIO standalone提供的示例代码。在一个运行的示例中,我只向客户机添加了一个自定义send()方法,并添加了一个main来执行客户机和服务器

编辑 我还尝试使用
asio::io_服务::工作(io_服务)
但是客户端在握手后仍然什么也不做

class session{
public:
    session(asio::io_service& io_service,
            asio::ssl::context& context)
        : socket_(io_service, context)  { }

    ssl_socket::lowest_layer_type& socket(){
        return socket_.lowest_layer();
    }

    void start(){
        std::cout << " Session start "<< "\n";
        socket_.async_handshake(asio::ssl::stream_base::server,
                                std::bind(&session::handle_handshake, this,
                                          std::placeholders::_1));
    }

    void handle_handshake(const asio::error_code& error){
        if (!error){
            std::cout << " Session handshake success "<< "\n";
            socket_.async_read_some(asio::buffer(data_, max_length),
                                    std::bind(&session::handle_read, this,
                                              std::placeholders::_1, std::placeholders::_2));
        }
        else {
            std::cout << " Session handshake failed "<< "\n";
            delete this;
        }
    }

    void handle_read(const asio::error_code& error,
                     size_t bytes_transferred) {
        if (!error) {
            std::cout << " Session Read success "<< "\n";
            asio::async_write(socket_,
                              asio::buffer(data_, bytes_transferred),
                              std::bind(&session::handle_write, this,
                                        std::placeholders::_1));
        }
        else {
            std::cout << " Session Read failed "<< "\n";
            delete this;
        }
    }

    void handle_write(const asio::error_code& error){
        if (!error){
            std::cout << " Write success "<< "\n";
            socket_.async_read_some(asio::buffer(data_, max_length),
                                    std::bind(&session::handle_read, this,
                                              std::placeholders::_1,
                                              std::placeholders::_2));
        }
        else{
            delete this;
        }
    }

private:
    ssl_socket socket_;
    enum { max_length = 1024 };
    char data_[max_length];
};

class server
{
public:
    server(asio::io_service& io_service, unsigned short port)
        : io_service_(io_service),
          acceptor_(io_service,
                    asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port)),
          context_(asio::ssl::context::sslv23) {
        context_.set_options(
                    asio::ssl::context::default_workarounds
                    | asio::ssl::context::no_sslv2
                    | asio::ssl::context::single_dh_use);
        context_.set_password_callback(std::bind(&server::get_password, this));
        context_.use_certificate_chain_file("server.pem");
        context_.use_private_key_file("server.pem", asio::ssl::context::pem);
        context_.use_tmp_dh_file("dh1024.pem");

        start_accept();
    }

    std::string get_password() const{
        return "test";
    }

    void start_accept(){
        std::cout << " Server accept start "<< "\n";
        session* new_session = new session(io_service_, context_);
        acceptor_.async_accept(new_session->socket(),
                               std::bind(&server::handle_accept, this, new_session,
                                         std::placeholders::_1));
    }

    void handle_accept(session* new_session,
                       const asio::error_code& error){
        if (!error){
            std::cout << " Server Accept success "<< "\n";
            new_session->start();
        }
        else
        {
            delete new_session;
        }

        start_accept();
    }

private:
    asio::io_service& io_service_;
    asio::ip::tcp::acceptor acceptor_;
    asio::ssl::context context_;
};


enum { max_length = 1024 };

class client
{
public:
    client(asio::io_service& io_service,
           asio::ssl::context& context,
           asio::ip::tcp::resolver::iterator endpoint_iterator)
        : socket_(io_service, context) {
        socket_.set_verify_mode(asio::ssl::verify_peer);
        socket_.set_verify_callback(
                    std::bind(&client::verify_certificate, this, std::placeholders::_1, std::placeholders::_2));

        asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
                            std::bind(&client::handle_connect, this,
                                      std::placeholders::_1));
    }

    bool verify_certificate(bool preverified,
                            asio::ssl::verify_context& ctx){
        return true;
    }

    void handle_connect(const asio::error_code& error){

        if (!error){
            std::cout << "Client Connect success "<< "\n";
            socket_.async_handshake(asio::ssl::stream_base::client,
                                    std::bind(&client::handle_handshake, this,
                                              std::placeholders::_1));
        }
        else {
            std::cout << "Client Connect failed: " << error.message() << "\n";
        }
    }

    void handle_handshake(const asio::error_code& error){
        if (!error) {
            std::cout << "Client Handshake success "<< "\n";
            //send("test") no send here
        }
        else{
            std::cout << "Client Handshake failed: " << error.message() << "\n";
        }
    }


    void send(char * request_){
        std::cout << " Client Sende daten "<< "\n";
        size_t request_length = strlen(request_);

        asio::async_write(socket_,
                          asio::buffer(request_, request_length),
                          std::bind(&client::handle_write, this,
                                    std::placeholders::_1,
                                    std::placeholders::_2));
    }

    void handle_write(const asio::error_code& error, size_t bytes_transferred){
        if (!error)
        {
            std::cout << " Client Write success "<< "\n";
            asio::async_read(socket_,
                             asio::buffer(reply_, bytes_transferred),
                             std::bind(&client::handle_read, this,
                                       std::placeholders::_1,
                                       std::placeholders::_2));
        }
        else {
            std::cout << "Client Write failed: " << error.message() << "\n";
        }
    }

    void handle_read(const asio::error_code& error,  size_t bytes_transferred) {
        if (!error)  {
            std::cout << "Client Reply: ";
            std::cout.write(reply_, bytes_transferred);
            std::cout << "\n";
        }
        else {
            std::cout << "Client Read failed: " << error.message() << "\n";
        }
    }

private:
    asio::ssl::stream<asio::ip::tcp::socket> socket_;
    char request_[max_length];
    char reply_[max_length];
};

using namespace std;

int main(){

    std::thread t {
        [](){
            asio::io_service server_service;
            server s(server_service, 8877);
            server_service.run();
        }
    };

    std::this_thread::sleep_for(std::chrono::milliseconds(3000));
    asio::io_service io_service;

    asio::ip::tcp::resolver resolver(io_service);
    asio::ip::tcp::resolver::query query("127.0.0.1", std::to_string(8877));
    asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);

    asio::ssl::context ctx(asio::ssl::context::sslv23);
    ctx.load_verify_file("ca.pem");

    client c(io_service, ctx, iterator);
    c.send("test");
    io_service.run();

    t.join();

    return 0;
}
课堂会话{
公众:
会话(asio::io_服务和io_服务,
asio::ssl::上下文和上下文)
:套接字(io_服务,上下文){}
ssl_套接字::最低层_层_类型和套接字(){
返回套接字。最低层();
}
void start(){
标准::cout