尝试重新连接到服务器

时间:2018-03-20 02:34:54

标签: c++ boost boost-asio

我需要编写一个处理ssl连接(读/写字符数组)到黑盒服务器的类。我需要实现断开/连接功能。但它没有按预期工作。

用例:

  • 用户连接到服务器(工作:可以发送和接收消息)
  • 用户断开与服务器的连接,等待一段时间,然后重新连接。 (失败:它仅在持续时间很短时起作用:如10秒。如果长于handle_connect()则返回错误connection timed out

以下是该类的源代码以及我如何使用它:

boost::asio::io_service &mioService;
SSLHandler* mpSSLConnection;

void Connector::setupConnection()
{
    try{

        std::string port = std::to_string(mPort);
        boost::asio::ip::tcp::resolver resolver(mioService);
        boost::asio::ip::tcp::resolver::query query(mHost, port);
        boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);

        boost::asio::ssl::context context(boost::asio::ssl::context::sslv23);
        //    context.load_verify_file("key.pem");


        if(mpSSLConnection == nullptr)
            mpSSLConnection = new SSLHandler(mioService,context,iterator,this);





    }catch (std::exception& e){
        std::cerr << "Exception: " << e.what() << "\n";
    }
    // actually this line is called from outside the func
    mpSSLConnection->connectToServer();
}

并像这样断开连接

void Connector::disconnect()
{
    isSetDisconnectedToSrv = true;
    mpSSLConnection->setIsDestructing(true);
    QThread::msleep(500);
    delete mpSSLConnection;
    mpSSLConnection = nullptr;
//    setupConnection();
    isConnectedToServer =false; // we did delete the object handle the ssl connection so...
    mpHandler->onServerDisconnected(); // just report to upper layer

}

最后,类源代码:

#ifndef SSLHANDLER_H
#define SSLHANDLER_H
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <queue>
#include <boost/lockfree/spsc_queue.hpp>

class Connector;
const int READ_SIZE =0;
const int READ_MSG=1;
class SSLHandler
{
public:




    SSLHandler(boost::asio::io_service& io_service, boost::asio::ssl::context& context, boost::asio::ip::tcp::resolver::iterator endpoint_iterator, Connector* pConnector)
    : socket_(io_service, context) , mEndpointIterator (endpoint_iterator) , mpConnector (pConnector),
    timer_{ io_service},
    isConnectionOk {false}
    {
        LOG_TRACE << "creating new sslhandler";
        socket_.set_verify_mode(boost::asio::ssl::context::verify_none);
        socket_.set_verify_callback(boost::bind(&SSLHandler::verify_certificate, this, _1, _2));


        mode = READ_SIZE;
    }
    ~SSLHandler();
    bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx);
    void handle_connect(const boost::system::error_code& error);
    void handle_handshake(const boost::system::error_code& error);
    void handle_write(const boost::system::error_code& error, size_t bytes_transferred);
    void handle_write_auth(const boost::system::error_code& error, size_t bytes_transferred);
    void handle_read_msgsize(const boost::system::error_code& error, size_t bytes_transferred);
    void handle_read_message(const boost::system::error_code& error, size_t bytes_transferred);
    void connectToServer();
    void do_reconnect();
    void handle_reconnect_timer(boost::system::error_code ec);

    void writeMessage(std::vector<char> &array);

    void setRequestMsg(std::vector<char> &&array);


    void setIsDestructing(bool value);

private:
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
    boost::asio::ip::tcp::resolver::iterator mEndpointIterator;
    boost::asio::deadline_timer timer_;
    char reply_[0x1 << 16]; //=65356 bytes
    int mode;
    uint32_t size;
    std::vector<char> requestMsg;
    std::vector<char> replyMsg;
    Connector* mpConnector; // ptr to object compose message
    std::queue<std::vector < char> >  mQueueMsg;
    bool isConnectionOk;
    bool isDestructing =false;

private:
    void writeMessageWithQueue(std::vector<char> &array);

};

#endif // SSLHANDLER_H

#include "sslhandler.h"
#include "connector.h"
#include "BoostLogger.h"
#include <QThread>
#include "boost/enable_shared_from_this.hpp"
SSLHandler::~SSLHandler()
{
    LOG_FATAL << "ssl handler shutdown";
    if(isConnectionOk){
        socket_.lowest_layer().close();
        boost::system::error_code ec;
        socket_.shutdown(ec);
        if(ec){
            LOG_FATAL << "ssl handler socket shutdown with err: " << ec.message();
        }

        LOG_TRACE << "ssl handler shutdown complete";
    }

}

bool SSLHandler::verify_certificate(bool preverified, boost::asio::ssl::verify_context &ctx)
{
    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:\n" << subject_name << std::endl;

    return preverified;
}

void SSLHandler::handle_connect(const boost::system::error_code &error)
{
    if(isDestructing){
        LOG_TRACE << "Is destructing ssl connect so abort " ;
        return;
    }
    LOG_TRACE << "get past destructing";
    if(!error){
        isConnectionOk = true;
        LOG_TRACE << "Connection OK!" << std::endl;
        socket_.async_handshake(boost::asio::ssl::stream_base::client, boost::bind(&SSLHandler::handle_handshake, this, boost::asio::placeholders::error));
    }else{
        LOG_FATAL << "Connect failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }
}

void SSLHandler::handle_handshake(const boost::system::error_code &error)
{
    if(isDestructing){
        LOG_TRACE << "Is destructing ssl connect so abort " ;
        return;
    }
    if(!error){
        std::cout << "Sending request: " << std::endl;


        boost::asio::async_write(socket_,
           boost::asio::buffer(requestMsg.data(), requestMsg.size()),
           boost::bind(&SSLHandler::handle_write_auth, this,
               boost::asio::placeholders::error,
               boost::asio::placeholders::bytes_transferred));
    }else{
        LOG_FATAL << "Handshake failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }
}

void SSLHandler::handle_write(const boost::system::error_code &error, size_t bytes_transferred)
{
    if(isDestructing){
        LOG_TRACE << "Is destructing ssl connect so abort " ;
        return;
    }

    if (error) {
        LOG_FATAL << "Write failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }

    Q_UNUSED(bytes_transferred);
    usleep(1e4);

    if (!mQueueMsg.empty()) {
        mQueueMsg.pop();
        if(!mQueueMsg.empty()){
            auto msg = mQueueMsg.front();
            writeMessageWithQueue(msg);
        }



    }
    else{
        LOG_ERROR << "Empty queue messages!";
    }



}

void SSLHandler::handle_write_auth(const boost::system::error_code &error, size_t bytes_transferred)
{
    usleep(1e5);
    if(isDestructing){
        LOG_TRACE << "Is destructing ssl connect so abort " ;
        return;
    }

    if (!error){
        if(mode==READ_SIZE){
            mode = READ_MSG;
            std::cerr << "\nSending request read size OK!\n" << std::endl;
            //      char respond[bytes_transferred] = "";
            boost::asio::async_read(socket_, boost::asio::buffer(reply_,4),
                boost::bind(&SSLHandler::handle_read_msgsize,
                    this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
//            std::cerr << "respond is " ;
        }


    }else{
        LOG_FATAL << "Write failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }
}

void SSLHandler::handle_read_msgsize(const boost::system::error_code &error, size_t bytes_transferred)
{
    if(isDestructing){
        LOG_TRACE << "Is destructing ssl connect so abort " ;
        return;
    }
    if (!error){
        //first 4 bytes contain size of message
        size = getFirstFour();

        mode = READ_SIZE;
        boost::asio::async_read(socket_, boost::asio::buffer(reply_,size),
            boost::bind(&SSLHandler::handle_read_message,
                this,
//                                            mWriteId++,
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred));





    }else{
        LOG_FATAL << "Read failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }
}

void SSLHandler::handle_read_message(const boost::system::error_code &error, size_t bytes_transferred)
{
    if(isDestructing){
        LOG_TRACE << "Is destructing ssl connect so abort " ;
        return;
    }
    if (!error){


        replyMsg.clear();
        replyMsg.assign(reply_,reply_+ size);
        mpConnector->setReadMsg(replyMsg);

        mode = READ_SIZE;

        // read next message size
        boost::asio::async_read(socket_, boost::asio::buffer(reply_,4),
            boost::bind(&SSLHandler::handle_read_msgsize,
                this,
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred));

    }else{
        LOG_FATAL << "Read failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }
}

void SSLHandler::connectToServer()
{
//    boost::asio::ip::tcp::resolver r(socket_.get_io_service());
    if(isDestructing){
        LOG_TRACE << "Is destructing ssl connect so abort " ;
        return;
    }
    boost::asio::async_connect(socket_.lowest_layer(), mEndpointIterator, boost::bind(&SSLHandler::handle_connect, this, boost::asio::placeholders::error));
    LOG_TRACE << "async_connect called";
}

void SSLHandler::do_reconnect()
{
//    return;
    if(isDestructing){
        LOG_TRACE << "Is destructing ssl connect so abort " ;
        return;
    }
//    socket_.shutdown();
    isConnectionOk = false;

    else{
        socket_.lowest_layer().cancel();
        timer_.expires_from_now(boost::posix_time::millisec(500));
        timer_.async_wait(boost::bind(&SSLHandler::handle_reconnect_timer, this, boost::asio::placeholders::error()));
    }

}

void SSLHandler::handle_reconnect_timer(boost::system::error_code ec)
{
    if(!ec){
        connectToServer();
    }
    else{
        LOG_TRACE << "Error with reconnect timer : " << ec.message();
    }
}

void SSLHandler::writeMessageWithQueue(std::vector<char> &array)
{

//    std::cerr << "write : " << (void*) array.data() << " | " << array.size() << std::endl;
    if(isDestructing){
        LOG_TRACE << "Is destructing ssl connect so abort " ;
        return;
    }
    boost::asio::async_write(socket_,
       boost::asio::buffer(array.data(), array.size()),
       boost::bind(&SSLHandler::handle_write, this,
           boost::asio::placeholders::error,
           boost::asio::placeholders::bytes_transferred));
}

void SSLHandler::writeMessage(std::vector<char> &array)
{
    if(mQueueMsg.size()==0){
        mQueueMsg.push(array);
        writeMessageWithQueue(array);
    }

    else
        mQueueMsg.push(array);


}
void SSLHandler::setRequestMsg(std::vector<char> &&array)
{
    requestMsg = std::move(array);
}
void SSLHandler::setIsDestructing(bool value)
{
    LOG_INFO << "ssl connection destructing set as " << value;
    isDestructing = value;
    if(isDestructing == true){
        if(isConnectionOk){
            socket_.lowest_layer().cancel();
            //        socket_.shutdown();
            LOG_INFO << "ssl connection destructing get pass shutdown";
        }
    }
}

PS:这是handler tracking,这很奇怪,在(调用)disconnect()之后再次重新连接:没有被解雇,所以建立连接后没有握手:(

  

@asio | 1521627714.863517 | 0 | resolver@0x7fbe2affc898.cancel空fz   params!清空fz规则!清空fz param!@asio ____________ socket_:   0x7fbe10005150 @asio ____________ 192.168.2.36   @asio | 1521627714.864161 | 0 * 1 | socket@0x7fbe10005150.async_connect @asio:   连接叫@asio | 1521627714.865136 |&gt; 1 | ec = system:0   @asio | 1521627714.865375 | 1 * 2 | socket@0x7fbe10005150.async_send   @asio | 1521627714.865416 |&LT; 1 |   @asio | 1521627714.865421 |→2 | EC =系统:0,bytes_transferred = 517   @asio | 1521627714.865429 | 2 * 3 | socket@0x7fbe10005150.async_receive   @asio | 1521627714.865451 |&2 |   @asio | 1521627714.866829 |→3 | EC =系统:0,bytes_transferred = 994   @asio | 1521627714.867764 | 3 * 4 | socket@0x7fbe10005150.async_send   @asio | 1521627714.867792 |&LT; 3 |   @asio | 1521627714.867798 |→4 | EC =系统:0,bytes_transferred = 326   @asio | 1521627714.867809 | 4 * 5 | socket@0x7fbe10005150.async_receive   @asio | 1521627714.867817 |&LT; 4 |   @asio | 1521627714.870094 |→5 | EC =系统:0,bytes_transferred = 234   @asio | 1521627714.870271 | 5 * 6 | socket@0x7fbe10005150.async_send   @asio | 1521627714.870318 |小于5 |   @asio | 1521627714.870333 |→6 | EC =系统:0,bytes_transferred = 154   @asio | 1521627714.970430 | 6 * 7 | socket@0x7fbe10005150.async_receive   @asio | 1521627714.970443 |&10 6 |   @asio | 1521627714.970449 |大于7 | EC =系统:0,bytes_transferred = 138   @asio | 1521627714.970470 | 7 * 8 | socket@0x7fbe10005150.async_receive   @asio | 1521627714.970475 |&LT; 7 |   @asio | 1521627714.970479 |&GT; 8 | EC =系统:0,bytes_transferred = 0   @asio | 1521627714.971418 | 8 * 9 | socket@0x7fbe10005150.async_send   @asio | 1521627714.971771 | 8 * 10 | deadline_timer@0x5290628.async_wait   @asio | 1521627714.972004 | 8 * 11 | socket@0x7fbe10005150.async_receive   @asio | 1521627714.972012 |&LT; 8 |   @asio | 1521627714.972017 |&GT; 9 | EC =系统:0,bytes_transferred = 138   @asio | 1521627714.982098 | 9 * 12 | socket@0x7fbe10005150.async_send   @asio | 1521627714.982115 |Δ9 |   @asio | 1521627714.982121 |&GT; 12 | EC =系统:0,bytes_transferred = 138   @asio | 1521627714.992214 | 12 * 13 | socket@0x7fbe10005150.async_send   @asio | 1521627714.992244 |&LT; 12 |   @asio | 1521627714.992255 |&GT; 11 | EC =系统:0,bytes_transferred = 292   @asio | 1521627714.992278 | 11 * 14 | socket@0x7fbe10005150.async_receive   @asio | 1521627714.992284 |&LT; 11 |   @asio | 1521627714.992290 |&GT; 13 | EC =系统:0,bytes_transferred = 186   @asio | 1521627715.002355 |δ13 |   @asio | 1521627715.002363 |&GT; 14 | EC =系统:0,bytes_transferred = 0   @asio | 1521627715.002469 | 14 * 15 | socket@0x7fbe10005150.async_receive   @asio | 1521627715.002479 |&LT; 14 |   @asio | 1521627715.002487 |→15 | EC =系统:0,bytes_transferred = 0   @asio | 1521627715.002495 | 15 * 16 | socket@0x7fbe10005150.async_receive   @asio | 1521627715.002500 |&LT; 15 |   @asio | 1521627715.002505 |&GT; 16 | EC =系统:0,bytes_transferred = 0   @asio | 1521627715.002550 | 16 * 17 | socket@0x7fbe10005150.async_receive   @asio | 1521627715.002561 |&LT; 16 |   @asio | 1521627715.002566 |&GT; 17 | EC =系统:0,bytes_transferred = 154   @asio | 1521627715.002581 | 17 * 18 | socket@0x7fbe10005150.async_receive   @asio | 1521627715.002586 |&LT; 17 |   @asio | 1521627715.002590 |&GT; 18 | EC =系统:0,bytes_transferred = 0   @asio | 1521627715.002636 | 18 * 19 | socket@0x7fbe10005150.async_receive   @asio | 1521627715.002653 |&LT; 18 | @asio | 1521627721.861983 |→10 | EC =系统:0   @asio | 1521627721.862105 | 10 * 20 | socket@0x7fbe10005150.async_send   @asio | 1521627721.862139 | 10 | deadline_timer@0x5290628.cancel   @asio | 1521627721.862144 | 10 * 21 | deadline_timer@0x5290628.async_wait   @asio | 1521627721.862258 |&LT; 10 |   @asio | 1521627721.862268 |→20 | EC =系统:0,bytes_transferred = 138   @asio | 1521627721.872365 |&小于20 |   @asio | 1521627721.872398 |&GT; 19 | EC =系统:0,bytes_transferred = 138   @asio | 1521627721.872436 | 19 * 22 | socket@0x7fbe10005150.async_receive   @asio | 1521627721.872443 |&LT; 19 |   @asio | 1521627721.872447 |&GT; 22 | EC =系统:0,bytes_transferred = 0   @asio | 1521627721.872503 | 22 * 23 | socket@0x7fbe10005150.async_receive   @asio | 1521627721.872515 |&LT; 22 | @asio | 1521627724.861966 |&GT; 21 | EC =系统:0   @asio | 1521627724.862091 | 21 * 24 | socket@0x7fbe10005150.async_send   @asio | 1521627724.862148 | 21 | deadline_timer@0x5290628.cancel   @asio | 1521627724.862157 | 21 * 25 | deadline_timer@0x5290628.async_wait   @asio | 1521627724.862272 |&LT; 21 |   @asio | 1521627724.862286 |&GT; 24 | EC =系统:0,bytes_transferred = 138   @asio | 1521627724.872375 |&LT; 24 |   @asio | 1521627724.872409 |&GT; 23 | EC =系统:0,bytes_transferred = 138   @asio | 1521627724.872457 | 23 * 26 | socket@0x7fbe10005150.async_receive   @asio | 1521627724.872465 |&LT; 23 |   @asio | 1521627724.872469 |&GT; 26 | EC =系统:0,bytes_transferred = 0   @asio | 1521627724.872510 | 26 * 27 | socket@0x7fbe10005150.async_receive   @asio | 1521627724.872516 |&LT; 26 | @asio | 1521627727.861968 |→25 | EC =系统:0   @asio | 1521627727.862084 | 25 * 28 | socket@0x7fbe10005150.async_send   @asio | 1521627727.862120 | 25 | deadline_timer@0x5290628.cancel   @asio | 1521627727.862125 | 25 * 29 | deadline_timer@0x5290628.async_wait   @asio | 1521627727.862204 |&LT; 25 |   @asio | 1521627727.862211 |&GT; 28 | EC =系统:0,bytes_transferred = 138   @asio | 1521627727.872283 |&LT; 28 |   @asio | 1521627727.872314 |&GT; 27 | EC =系统:0,bytes_transferred = 138   @asio | 1521627727.872362 | 27 * 30 | socket@0x7fbe10005150.async_receive   @asio | 1521627727.872366 |&LT; 27 |   @asio | 1521627727.872371 |→30 | EC =系统:0,bytes_transferred = 0   @asio | 1521627727.872412 | 30 * 31 | socket@0x7fbe10005150.async_receive   @asio | 1521627727.872418 |小于30 | @asio | 1521627730.861967 |&GT; 29 | EC =系统:0   @asio | 1521627730.862072 | 29 * 32 | socket@0x7fbe10005150.async_send   @asio | 1521627730.862118 | 29 | deadline_timer@0x5290628.cancel   @asio | 1521627730.862125 | 29 * 33 | deadline_timer@0x5290628.async_wait   @asio | 1521627730.862217 |&LT; 29 |   @asio | 1521627730.862227 |&GT; 32 | EC =系统:0,bytes_transferred = 138   @asio | 1521627730.872315 |&LT; 32 |   @asio | 1521627730.872360 |&GT; 31 | EC =系统:0,bytes_transferred = 138   @asio | 1521627730.872406 | 31 * 34 | socket@0x7fbe10005150.async_receive   @asio | 1521627730.872412 |&LT; 31 |   @asio | 1521627730.872416 |&GT; 34 | EC =系统:0,bytes_transferred = 0   @asio | 1521627730.872458 | 34 * 35 | socket@0x7fbe10005150.async_receive   @asio | 1521627730.872465 |&LT; 34 | @asio | 1521627733.862001 |&GT; 33 | EC =系统:0   @asio | 1521627733.862114 | 33 * 36 | socket@0x7fbe10005150.async_send   @asio | 1521627733.862153 | 33 | deadline_timer@0x5290628.cancel   @asio | 1521627733.862158 | 33 * 37 | deadline_timer@0x5290628.async_wait   @asio | 1521627733.862244 |γ-33 |   @asio | 1521627733.862250 |&GT; 36 | EC =系统:0,bytes_transferred = 138   @asio | 1521627733.872342 |&LT; 36 |   @asio | 1521627733.872379 |→35 | EC =系统:0,bytes_transferred = 138   @asio | 1521627733.872416 | 35 * 38 | socket@0x7fbe10005150.async_receive   @asio | 1521627733.872422 |&γ-35 |   @asio | 1521627733.872424 |&GT; 38 | EC =系统:0,bytes_transferred = 0   @asio | 1521627733.872461 | 38 * 39 | socket@0x7fbe10005150.async_receive   @asio | 1521627733.872466 |&LT; 38 | @asio | 1521627736.861976 |&在37 | EC =系统:0   @asio | 1521627736.862158 | 37 * 40 | socket@0x7fbe10005150.async_send   @asio | 1521627736.862235 | 37 | deadline_timer@0x5290628.cancel   @asio | 1521627736.862242 | 37 * 41 | deadline_timer@0x5290628.async_wait   @asio | 1521627736.862406 |&{37 |   @asio | 1521627736.862414 |→40 | EC =系统:0,bytes_transferred = 138   @asio | 1521627736.872497 |&LT; 40 |   @asio | 1521627736.872555 |&GT; 39 | EC =系统:0,bytes_transferred = 138   @asio | 1521627736.872622 | 39 * 42 | socket@0x7fbe10005150.async_receive   @asio | 1521627736.872638 |&LT; 39 |   @asio | 1521627736.872641 |&GT; 42 | EC =系统:0,bytes_transferred = 0   @asio | 1521627736.872720 | 42 * 43 | socket@0x7fbe10005150.async_receive   @asio | 1521627736.872726 |&LT; 42 | @asio | 1521627739.861978 |&GT; 41 | EC =系统:0   @asio | 1521627739.862096 | 41 * 44 | socket@0x7fbe10005150.async_send   @asio | 1521627739.862144 | 41 | deadline_timer@0x5290628.cancel   @asio | 1521627739.862148 | 41 * 45 | deadline_timer@0x5290628.async_wait   @asio | 1521627739.862243 |&LT; 41 |   @asio | 1521627739.862249 |&GT; 44 | EC =系统:0,bytes_transferred = 138   @asio | 1521627739.872335 |&LT; 44 |   @asio | 1521627739.872375 |&GT; 43 | EC =系统:0,bytes_transferred = 138   @asio | 1521627739.872421 | 43 * 46 | socket@0x7fbe10005150.async_receive   @asio | 1521627739.872425 |&LT; 43 |   @asio | 1521627739.872429 |&GT; 46 | EC =系统:0,bytes_transferred = 0   @asio | 1521627739.872477 | 46 * 47 | socket@0x7fbe10005150.async_receive   @asio | 1521627739.872492 |&LT; 46 | @asio | 1521627742.861953 |&GT; 45 | EC =系统:0   @asio | 1521627742.862121 | 45 * 48 | socket@0x7fbe10005150.async_send   @asio | 1521627742.862204 | 45 | deadline_timer@0x5290628.cancel   @asio | 1521627742.862211 | 45 * 49 | deadline_timer@0x5290628.async_wait   @asio | 1521627742.862392 |&LT; 45 |   @asio | 1521627742.862406 |&GT; 48 | EC =系统:0,bytes_transferred = 138   @asio | 1521627742.872491 |&LT; 48 |   @asio | 1521627742.872543 |&GT; 47 | EC =系统:0,bytes_transferred = 138   @asio | 1521627742.872592 | 47 * 50 | socket@0x7fbe10005150.async_receive   @asio | 1521627742.872600 |&LT; 47 |   @asio | 1521627742.872605 |→50 | EC =系统:0,bytes_transferred = 0   @asio | 1521627742.872675 | 50 * 51 | socket@0x7fbe10005150.async_receive   @asio | 1521627742.872688 |&LT; 50 |   @asio | 1521627745.316714 | 0 | socket@0x7fbe10005150.close   @asio | 1521627745.316777 |&GT; 51 | EC =系统:125,bytes_transferred = 0   @asio | 1521627745.316858 |的51 | @asio:~SSLHandler   @asio | 1521627745.817594 | 0 | resolver@0x7fbe00ff8758.cancel   @asio | 1521627745.861965 |&gt; 49 | ec = system:0 @asio | 1521627745.861984 |&lt; 49 |   @asio | 1521627749.757091 | 0 | resolver@0x7fbe00ff8648.cancel   @asio____________ socket_:0x7fbde4008890   @asio ____________ 192.168.2.36   @asio | 1521627749.757178 | 0 * 52 | socket@0x7fbde4008890.async_connect   @asio:connect called

1 个答案:

答案 0 :(得分:1)

我修复了自包含的样本,并将其运行到演示服务器上:

#include <iostream>
#include <sstream>
#include <vector>

#ifdef STANDALONE
    namespace {
        struct LogTx {
            std::stringstream _ss;
            std::ostream& _os;
            bool _armed = true;

            LogTx(std::ostream& os) : _os(os) {}
            LogTx(LogTx&& rhs) : _ss(std::move(rhs._ss)), _os(rhs._os) { rhs._armed = false; }
            ~LogTx() { if (_armed) _os << _ss.rdbuf() << std::endl; }

            LogTx operator<<(std::ostream&(&v)(std::ostream&)) { _ss << v; return std::move(*this); }
            template <typename T> LogTx operator<<(T&& v) { _ss << v; return std::move(*this); }
        };

    }

#   define LOG_FATAL LogTx(std::cerr) << "FATAL: "
#   define LOG_TRACE LogTx(std::clog) << "TRACE: "
#   define LOG_ERROR LogTx(std::cerr) << "ERROR: "
#   define LOG_INFO  LogTx(std::clog) << "INFO:  "
#   define Q_UNUSED(a) static_cast<void>(a)

    namespace {
        struct Connector {
            void sendDisconnectedStatus()               { LOG_INFO << "Disconnected"; }
            void setReadMsg(std::vector<char> const& v) { LOG_INFO << "response: '" << std::string(v.begin(), v.end()) << "'"; }
        };
    }
#endif

#ifndef SSLHANDLER_H
#define SSLHANDLER_H
#include <boost/endian/arithmetic.hpp> // for big_uint32_t
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <queue>
#include <string>
#include <thread>

const int READ_SIZE = 0;
const int READ_MSG = 1;

class SSLHandler {
  public:
    SSLHandler(boost::asio::io_service &io_service, boost::asio::ssl::context &context,
               boost::asio::ip::tcp::resolver::iterator endpoint_iterator, Connector *pConnector)
            : socket_(io_service, context), mEndpointIterator(endpoint_iterator),
              mpConnector(pConnector), timer_{ io_service }, isConnectionOk{ false } 
    {
        LOG_TRACE << "creating new sslhandler";
        socket_.set_verify_mode(boost::asio::ssl::context::verify_none);
        socket_.set_verify_callback(boost::bind(&SSLHandler::verify_certificate, this, _1, _2));

        mode = READ_SIZE;
    }
    ~SSLHandler();
    bool verify_certificate(bool preverified, boost::asio::ssl::verify_context &ctx);
    void handle_connect(const boost::system::error_code &error);
    void handle_handshake(const boost::system::error_code &error);
    void handle_write(const boost::system::error_code &error, size_t bytes_transferred);
    void handle_write_auth(const boost::system::error_code &error, size_t bytes_transferred);
    void handle_read_msgsize(const boost::system::error_code &error, size_t bytes_transferred);
    void handle_read_message(const boost::system::error_code &error, size_t bytes_transferred);
    void connectToServer();
    void do_reconnect();
    void handle_reconnect_timer(boost::system::error_code ec);

    void writeMessage(std::vector<char> &array);

    void setRequestMsg(std::vector<char> &&array);

    void setIsDestructing(bool value);

  private:
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
    boost::asio::ip::tcp::resolver::iterator mEndpointIterator;
    Connector *mpConnector; // ptr to object compose message
    boost::asio::deadline_timer timer_;
    char reply_[0x1 << 16]; //=65356 bytes

    size_t getFirstFour() {
        return *boost::asio::buffer_cast<boost::endian::big_uint32_t *>(boost::asio::buffer(reply_));
    };

    int mode;
    uint32_t size;
    std::vector<char> requestMsg;
    std::vector<char> replyMsg;
    std::queue<std::vector<char> > mQueueMsg;
    bool isConnectionOk;
    bool isDestructing = false;

  private:
    void writeMessageWithQueue(std::vector<char> &array);
};

#endif // SSLHANDLER_H

//#include "sslhandler.h"
//#include "connector.h"
//#include "BoostLogger.h"
//#include <QThread>
//#include "boost/enable_shared_from_this.hpp"

SSLHandler::~SSLHandler() {
    LOG_FATAL << "ssl handler shutdown";
    if (isConnectionOk) {
        socket_.lowest_layer().close();
        boost::system::error_code ec;
        socket_.shutdown(ec);
        if (ec) {
            LOG_FATAL << "ssl handler socket shutdown with err: " << ec.message();
        }

        LOG_TRACE << "ssl handler shutdown complete";
    }
}

bool SSLHandler::verify_certificate(bool preverified, boost::asio::ssl::verify_context &ctx) {
    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:\n" << subject_name << std::endl;

    return preverified;
}

void SSLHandler::handle_connect(const boost::system::error_code &error) {
    if (isDestructing) {
        LOG_TRACE << "Is destructing ssl connect so abort ";
        return;
    }
    LOG_TRACE << "get past destructing";
    if (!error) {
        isConnectionOk = true;
        LOG_TRACE << "Connection OK!" << std::endl;
        socket_.async_handshake(boost::asio::ssl::stream_base::client,
                                boost::bind(&SSLHandler::handle_handshake, this, boost::asio::placeholders::error));
    } else {
        LOG_FATAL << "Connect failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }
}

void SSLHandler::handle_handshake(const boost::system::error_code &error) {
    if (isDestructing) {
        LOG_TRACE << "Is destructing ssl connect so abort ";
        return;
    }
    if (!error) {
        std::cout << "Sending request: " << std::endl;

        boost::asio::async_write(socket_, boost::asio::buffer(requestMsg.data(), requestMsg.size()),
                                 boost::bind(&SSLHandler::handle_write_auth, this, boost::asio::placeholders::error,
                                             boost::asio::placeholders::bytes_transferred));
    } else {
        LOG_FATAL << "Handshake failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }
}

void SSLHandler::handle_write(const boost::system::error_code &error, size_t bytes_transferred) {
    if (isDestructing) {
        LOG_TRACE << "Is destructing ssl connect so abort ";
        return;
    }

    if (error) {
        LOG_FATAL << "Write failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }

    Q_UNUSED(bytes_transferred);
    std::this_thread::sleep_for(std::chrono::milliseconds(10));

    if (!mQueueMsg.empty()) {
        mQueueMsg.pop();
        if (!mQueueMsg.empty()) {
            auto msg = mQueueMsg.front();
            writeMessageWithQueue(msg);
        }

    } else {
        LOG_ERROR << "Empty queue messages!";
    }
}

void SSLHandler::handle_write_auth(const boost::system::error_code &error, size_t bytes_transferred) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    if (isDestructing) {
        LOG_TRACE << "Is destructing ssl connect so abort ";
        return;
    }

    if (!error) {
        if (mode == READ_SIZE) {
            mode = READ_MSG;
            std::cerr << "\nSending request read size OK!\n" << std::endl;
            //      char respond[bytes_transferred] = "";
            boost::asio::async_read(socket_, boost::asio::buffer(reply_, 4),
                                    boost::bind(&SSLHandler::handle_read_msgsize, this,
                                                boost::asio::placeholders::error,
                                                boost::asio::placeholders::bytes_transferred));
            //            std::cerr << "respond is " ;
        }

    } else {
        LOG_FATAL << "Write failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }
}

void SSLHandler::handle_read_msgsize(const boost::system::error_code &error, size_t bytes_transferred) {
    if (isDestructing) {
        LOG_TRACE << "Is destructing ssl connect so abort ";
        return;
    }
    if (!error) {
        // first 4 bytes contain size of message
        size = getFirstFour();
        LOG_TRACE << "Decoded size: " << size;

        mode = READ_SIZE;
        boost::asio::async_read(socket_, boost::asio::buffer(reply_, size),
                                boost::bind(&SSLHandler::handle_read_message, this,
                                            //                                            mWriteId++,
                                            boost::asio::placeholders::error,
                                            boost::asio::placeholders::bytes_transferred));

    } else {
        LOG_FATAL << "Read failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }
}

void SSLHandler::handle_read_message(const boost::system::error_code &error, size_t bytes_transferred) {
    if (isDestructing) {
        LOG_TRACE << "Is destructing ssl connect so abort ";
        return;
    }
    if (!error) {

        replyMsg.clear();
        replyMsg.assign(reply_, reply_ + size);
        mpConnector->setReadMsg(replyMsg);

        mode = READ_SIZE;

        // read next message size
        boost::asio::async_read(socket_, boost::asio::buffer(reply_, 4),
                                boost::bind(&SSLHandler::handle_read_msgsize, this, boost::asio::placeholders::error,
                                            boost::asio::placeholders::bytes_transferred));

    } else {
        LOG_FATAL << "Read failed: " << error.message() << std::endl;
        mpConnector->sendDisconnectedStatus();
        do_reconnect();
    }
}

void SSLHandler::connectToServer() {
    //    boost::asio::ip::tcp::resolver r(socket_.get_io_service());
    if (isDestructing) {
        LOG_TRACE << "Is destructing ssl connect so abort ";
        return;
    }
    boost::asio::async_connect(socket_.lowest_layer(), mEndpointIterator,
                               boost::bind(&SSLHandler::handle_connect, this, boost::asio::placeholders::error));
    LOG_TRACE << "async_connect called";
}

void SSLHandler::do_reconnect() {
    //    socket_.shutdown();
    isConnectionOk = false;
    //    return;
    if (isDestructing) {
        LOG_TRACE << "Is destructing ssl connect so abort ";
        return;
    } else {
        socket_.lowest_layer().cancel();
        timer_.expires_from_now(boost::posix_time::millisec(500));
        timer_.async_wait(boost::bind(&SSLHandler::handle_reconnect_timer, this, boost::asio::placeholders::error()));
    }
}

void SSLHandler::handle_reconnect_timer(boost::system::error_code ec) {
    if (!ec) {
        connectToServer();
    } else {
        LOG_TRACE << "Error with reconnect timer : " << ec.message();
    }
}

void SSLHandler::writeMessageWithQueue(std::vector<char> &array) {

    //    std::cerr << "write : " << (void*) array.data() << " | " << array.size() << std::endl;
    if (isDestructing) {
        LOG_TRACE << "Is destructing ssl connect so abort ";
        return;
    }
    boost::asio::async_write(socket_, boost::asio::buffer(array.data(), array.size()),
                             boost::bind(&SSLHandler::handle_write, this, boost::asio::placeholders::error,
                                         boost::asio::placeholders::bytes_transferred));
}

void SSLHandler::writeMessage(std::vector<char> &array) {
    if (mQueueMsg.size() == 0) {
        mQueueMsg.push(array);
        writeMessageWithQueue(array);
    }

    else
        mQueueMsg.push(array);
}
void SSLHandler::setRequestMsg(std::vector<char> &&array) { requestMsg = std::move(array); }
void SSLHandler::setIsDestructing(bool value) {
    LOG_INFO << "ssl connection destructing set as " << value;
    isDestructing = value;
    if (isDestructing == true) {
        if (isConnectionOk) {
            socket_.lowest_layer().cancel();
            //        socket_.shutdown();
            LOG_INFO << "ssl connection destructing get pass shutdown";
        }
    }
}

int main() {
    Connector c;

    boost::asio::io_service svc;
    boost::asio::ssl::context ctx(boost::asio::ssl::context_base::sslv23_client);

    SSLHandler h(svc, ctx, boost::asio::ip::tcp::resolver{svc}.resolve({{}, 6767}), &c);
    h.setRequestMsg({'h','e','l','l','o','\n','w','o','r','l','d'});
    h.connectToServer();

    svc.run();
}

现在,我没有看到任何问题,无论服务器在中断后需要多长时间才能恢复。

你提到

  

嗨,我的意思是用户主动呼叫断开功能(不像上次那样通过网络丢弃连接)。如果用户调用disconnect()然后等待超过10秒,则调用connect()连接失败,错误:连接超时。 - 巴顿11 hours ago

您的代码中没有disconnect()这样的功能,也无法看到它可能如何实现。因此,

  • 问题出在服务器端(停止接受连接或完成SSL握手?)
  • 问题在于您不会显示的代码