我的应用程序使用libssh2通过SSH进行通信,通常可以正常工作。我遇到的一个问题是远程主机意外死机 - 在这种情况下,远程主机是一个可能随时断电的嵌入式设备,因此这种情况并不罕见。
当发生这种情况时,我的应用检测到远程计算机已停止响应ping,并断开SSH连接的本地端,如下所示:
void SSHSession :: CleanupSession()
{
if (_uploadFileChannel)
{
libssh2_channel_free(_uploadFileChannel);
_uploadFileChannel = NULL;
}
if (_sendCommandsChannel)
{
libssh2_channel_free(_sendCommandsChannel);
_sendCommandsChannel = NULL;
}
if (_session)
{
libssh2_session_disconnect(_session, "bye bye");
libssh2_session_free(_session);
_session = NULL;
}
}
非常简单,但问题是libssh2_channel_free()调用可能会长时间阻塞,等待远程端响应“我现在要离开”消息,因为它已断电而永远不会这样做...但与此同时,我的应用程序被冻结(在清理程序中被阻止),这是不好的。
有没有办法(缺少黑客libssh2)来避免这种情况?我想拆掉本地SSH数据结构,在此拆除过程中永远不会阻塞。 (我想我可以简单地泄漏SSH会话内存,或者将它委托给另一个线程,但这些似乎是丑陋的黑客而不是正确的解决方案)
答案 0 :(得分:0)
我对libssh2没有经验,但也许我们可以通过使用libssh2_session_disconnect_ex
和不同的断开原因来解决libssh2中的不同行为:SSH_DISCONNECT_CONNECTION_LOST
。
libssh2_session_disconnect
相当于使用libssh2_session_disconnect_ex
,原因为SSH_DISCONNECT_BY_APPLICATION
。如果libssh2知道连接丢失了,也许它不会尝试与另一方交谈。
http://libssh2.sourceforge.net/doc/#libssh2sessiondisconnectex
答案 1 :(得分:0)
设置为非阻塞模式并通过设置回调函数来控制从套接字读取数据,使用libssh2_session_callback_set和cbstype的LIBSSH2_CALLBACK_RECV从soket读取数据
void *libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbtype, void *callback);
如果由于错误ENOTCONN无法从套接字读取数据,这意味着远程端已关闭套接字或连接失败,则在回调函数中返回-ENOTCONN