2017-07-04 39 views
0

我不明白如何关闭boost::asio ssl套接字。我尝试了几种方法,但总是会在某个时刻提出Segmentation fault尝试关闭SSL套接字时使用boost asio 1.64的分段错误(SIGSEGV)

我一直在阅读了下面的帖子来解决这种情况: boost asio ssl async_shutdown always finishes with an error?

具体来说,我想实现的

甲方启动关闭(),并等待乙方与一个 回应shutdown()

请注意,客户端和服务器都在localhost中运行。

下面是客户端代码:

typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLSocket; 

MyClass::MyClass(const std::string &url, 
    const std::string &port) throw() : 
    m_socket(NULL), m_url(url), m_port(port), m_isConnected(false) 
{ 
} 

void MyClass::disconnect() 
{ 
    // See the section "the disconnect method" 
} 

bool MyClass::tryConnect() throw() 
{ 
    boost::asio::io_service ioService; 
    boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); 
    m_socket = new SSLSocket(ioService, ctx); 

    tcp::resolver resolver(ioService); 
    tcp::resolver::query query(m_url, m_port); 

    tcp::resolver::iterator end; 
    tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); 

    boost::system::error_code error = boost::asio::error::host_not_found; 
    boost::asio::connect(m_socket->lowest_layer(), endpoint_iterator, error); 

    if(endpoint_iterator == end || error) 
    { 
    m_isConnected = false; 
    } 
    else 
    { 
    m_socket->set_verify_mode(boost::asio::ssl::verify_none); 
    m_socket->handshake(SSLSocket::client); 

    m_isConnected = true; 
    } 

    return m_isConnected; 
} 

void MyClass::write(const std::string &message) 
{ 
    boost::asio::write(*m_socket, boost::asio::buffer(message)); 
} 

std::string MyClass::readUntil(const std::string &until) 
{ 
    boost::asio::read_until(*m_socket, response, until); 
    ... 
    return response; 
} 

int main() 
{ 
    MyClass mc(...); 

    while(true) 
    { 
    bool connected = mc.isConnected(); 

    if(!connected) 
    { 
     connected = mc.tryConnect(); 
    } 

    if(connected) 
    { 
     mc.send(...); 
     std::string resp = mc.readUntil(...); 
     mc.disconnect(); 
    } 
    } 
} 

Disconnect方法

我已阅读的评论链接后,我已经更新了两个SSL服务器和客户端。现在,它们都执行shutdown()操作来正确关闭ssl连接,但关闭套接字时仍然出现错误。

我已经更新了disconnect()方法(总是在程序崩溃)如下:

... 
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> *m_socket; 
... 
void MyClass::disconnect() 
{ 
    // Shutdown the connection 
    // TODO is this the correct way to close a boost asio socket? 
    if(m_socket != NULL) 
    { 
    std::cout << "shutting down the socket, thread = " << 
     pthread_self() << std::endl; 

    // I have checked that the thread is always the same, so the problem 
    // is not related with race conditions or similar. 

    boost::system::error_code ec; 
    m_socket->lowest_layer().shutdown(
     boost::asio::ip::tcp::socket::shutdown_both, ec); 

    std::cout << 
     "Shut down, err = " << ec << ", " << 
     "Category: " << ec.category().name() << std::endl; 

    if(!ec) 
    { 
     std::cout << "closing the socket, thread = " << 
     pthread_self() << std::endl; 

     if(m_socket->lowest_layer().is_open()) 
     { 
     m_socket->lowest_layer().close(ec); 
     } 

     std::cout << 
     "Socket closed, err = " << ec << ", " << "Category: " << 
     ec.category().name() << std::endl; 

     if(!ec) 
     { 
     std::cout << "Deleting socket... " << std::endl; 
     delete m_socket; 
     m_socket = NULL; 
     std::cout << "Socket deleted" << std::endl; 
     } 
    } 
    } 

    m_isConnected = false; 
} 

错误回溯

的bkactrace(从断开法)是在这里:

#0 0x4158114f in boost::system::error_code::operator=<boost::asio::error::basic_errors> (this=0x1d, val=boost::asio::error::operation_aborted) 
    at .../include/boost/system/error_code.hpp:344 
#1 0x41587308 in boost::asio::detail::epoll_reactor::deregister_descriptor (this=0x46463045, descriptor=27, [email protected]: 0x8151ea8, 
    closing=true) at .../include/boost/asio/detail/impl/epoll_reactor.ipp:351 
#2 0x41588550 in boost::asio::detail::reactive_socket_service_base::close (this=0x812efbc, impl=..., ec=...) 
    at .../include/boost/asio/detail/impl/reactive_socket_service_base.ipp:104 
#3 0x415885da in boost::asio::stream_socket_service<boost::asio::ip::tcp>::close (this=0x812efa8, impl=..., ec=...) 
    at .../include/boost/asio/stream_socket_service.hpp:174 
#4 0x41588630 in boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >::close (this=0x812ef08, ec=...) 
    at .../include/boost/asio/basic_socket.hpp:385 
#5 0x41576383 in MyClass::disconnect (this=0x80a6f58) at ... 

检查frame 1,可以看出增加产生的错误是boost::asio::error::operation_aborted;

此外,运行用gdb的过程中,simetimes我看到下面的断言失败

pthread_mutex_lock.c:312: __pthread_mutex_lock_full: Assertion `(-(e)) != 3 || !robust' failed. 
+0

SIGABRT通常指示断言失败。你有没有检查崩溃的堆栈跟踪?你究竟如何杀死这个过程?在你的代码片段中没有线程,也没有信号处理。你也无缘无故地调用'resolver.resolve(query)'两次。 – VTT

+0

这个问题的答案可能会帮助你:[什么是安全断开asio SSL套接字的正确方法?](https://stackoverflow.com/questions/32046034/what-is-the-proper-way-to-安全断开-AN-ASIO-SSL-插座) – kenba

回答

0

我已经找到了问题。

我开扩的插座中的方法,如:

void connect() 
{ 
    ... 
    boost::asio::io_service m_ioService 
    ... 
    m_sock = new SSLSocket(m_ioService, ...) 
} 

connect方法返回,m_ioService超出范围,所以由于ioService插座崩溃已被删除。请注意,m_ioService通过引用传递,此外,它是不可复制的。