我有一个服务器应用程序的使用提高ASIO与若干客户。 服务器的应用程序运行在Linux服务器和客户的Windows上运行的桌面。
目前的设计是多线程的虽然只有一个提升ASIO thead(其运行 boost::asio::io_context
). 增ASIO线只负责读、写,并有一些罕见的派遣。 阅读是通过使用 boost::asio::async_read
但是副本所得到的消息使得另外一个线程可以做的工作的处理。 写的是通过使用 boost::asio::write
但是,该消息已经被复制和传送给提高ASIO线
在大多数情况下当一个客户断提高ASIO抛出一个错误,我关闭相关的插座,以及其他卯继续工作。 但是,如果一客户的Windows桌面上有一个电源故障的话 boost::asio::write
是写给他们,然后提升没有检测到的问题和悬挂在 boost::asio::write
. 它挂起差不多20分钟的时和服务器不能与其他客户在这个时候
从我在网上读者提高ASIO没有意引入一个超时参数。 我试图设置SO_SNDTIMEO5秒钟,但没有任何影响写挂起。 现在我最好的猜测来解决这个问题是给每个插座不同的线这样一个客户无法采取了其他客户。 是否有更好的选择比这个吗? 如果我做得到的每一座自己的线是不是意味着我需要一个 boost::asio::io_context
每个线程,以避免写挂?
编辑:在看到的评论意见,我试图重新功能的电话 boost::asio::write
与 boost::asio::async_write
. 下面我有一些代码,是简化为如此,但是仍然展示了总体的改变是:
最初与 boost::asio::write
:
inline void MessagingServer::writeMessage(
GuiSession* const a_guiSession,
const PB::Message& a_msg
) {
boost::asio::dispatch(m_guiIoIoContext, [this, a_guiSession, a_msg]() {
// I removed code that writes a_msg's bytes into m_guiIoWriteBuf
// and sets totalSize to simplify for SO
boost::system::error_code error;
boost::asio::write(a_guiSession->m_guiIoGsSocket, boost::asio::buffer(m_guiIoWriteBuf, totalSize), error);
if (UNLIKELY(error))
ERRLOG << a_guiSession->m_gsSessionId << " write failed: " << error.message();
});
}
与重做 boost::asio::async_write
:
inline void MessagingServer::writeMessage(
GuiSession* const a_guiSession,
const PB::Message& a_msg
) {
a_guiSession->m_tempMutex.lock();
boost::asio::dispatch(m_guiIoIoContext, [this, a_guiSession, a_msg]() {
// I removed code that writes a_msg's bytes into m_guiIoWriteBuf
// and sets totalSize to simplify for SO
boost::asio::async_write(
a_guiSession->m_guiIoGsSocket,
boost::asio::buffer(m_guiIoWriteBuf, totalSize),
[this, a_guiSession](const boost::system::error_code& a_error, std::size_t) {
if (UNLIKELY(a_error))
ERRLOG << a_guiSession->m_gsSessionId << " write failed: " << a_error.message();
a_guiSession->m_tempMutex.unlock();
}
);
});
}
锁被引入第二代码,以保证只有一个呼叫 boost::asio::async_write
是活的时间(我知道有更高性能的方式做到这一点,但这是简单的用于测试)。 这两个代码相同的问题挂提高ASIO时客户有一个电力故障。 但是他们挂在不同的方式,步码不允许提升ASIO执行的其他行动,只是没有进一步写到挂一个产生了一个错误
在一个独立的实验,我没有尝试的设置 SO_KEEPALIVE
但是,这也没解决的问题挂