我不明白如何關閉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.
SIGABRT通常指示斷言失敗。你有沒有檢查崩潰的堆棧跟蹤?你究竟如何殺死這個過程?在你的代碼片段中沒有線程,也沒有信號處理。你也無緣無故地調用'resolver.resolve(query)'兩次。 – VTT
這個問題的答案可能會幫助你:[什麼是安全斷開asio SSL套接字的正確方法?](https://stackoverflow.com/questions/32046034/what-is-the-proper-way-to-安全斷開-AN-ASIO-SSL-插座) – kenba