gpt4 book ai didi

c - libssh2:如何处理来自 ssh 服务器的未经请求的数据?

转载 作者:行者123 更新时间:2023-11-30 15:34:29 28 4
gpt4 key购买 nike

我有一个程序,使用 libssh2 来管理一些 Linux 机器。它相当简单:它连接到 Linux 机器,下载配置文件,然后保持 libssh2 连接打开(和空闲),以便如果用户按下 GUI 上的按钮,它可以根据需要向 Linux 机器发送适当的 shell 命令。

它使用非阻塞 I/O(通过 libssh2_session_set_blocking(session, 0)),以便网络 I/O 可以由单个线程处理,而 session A 的事件不会被 session B 阻塞读取或写入等

这一切基本上都工作正常。我说主要是因为只有当程序同时连接到许多(即几十个)盒子时才会出现一个奇怪的问题。所发生的情况是, session 全部正常连接,配置文件下载成功,并且连接全部空闲,正如预期的那样。但在一些 session 中,下载完成后几毫秒(即在我对所有配置文件字节执行 libssh2_channel_read() 后,以及在 libssh2_channel_close() 成功后),一些额外的数据字节(通常是 104 或140) 出现在 session 的 TCP 套接字上,可供我读取并传递给 libssh2。

此时我遇到了一个问题,因为(据我所知)libssh2 session 应该是空闲的,并且我不知道如何处理这些未经请求的数据字节。我的选择都不是真正令人满意:

  • 我可以忽略这些字节,但是 select() 会不断醒来,因为字节在那里,这会导致线程旋转,并且只要程序打开,我的 CPU 使用率就会显着上升,所以这不好。

  • 我可以在带有额外数据的套接字上停止 select()-ing,但随后我无法判断套接字是否被远程对等方关闭,并且我希望能够在发生这种情况时通知用户。

  • 我可以直接recv()多余的字节并将它们扔掉,但这显然会搞乱libssh2连接状态机的状态,因为下次我尝试使用它时(例如,当用户希望我向机器发送 ssh 命令)该命令未发送。

  • 我可以执行 sleep(1) 或关闭连接并重新连接,但对于我认为应该正确处理的问题来说,这些都是丑陋的解决方法。

所以我的问题是

  • 这些奇怪的未经请求的字节是什么?

  • 我应该调用什么函数将它们传递给 libssh2 以使其满意?

ps 以下是一些神秘接收字节的示例,通过使用 MSG_PEEK 标志执行 recv() 获得:

--- peek'd data from session #1 (104 bytes): --------------------------------------------
0000: ..#|)62.!.A..... [ab 1f 23 7c 29 36 32 e8 21 cf 41 91 88 de 06 a4]
0016: xc.??n.+aJLS..di [78 63 f2 3f 3f 6e 16 2b 61 4a 4c 53 ab aa 64 69]
0032: ...d.]f.P...4;.3 [c2 d6 9e 64 b4 5d 66 db 50 ba 90 82 34 3b cc 33]
0048: cO"..5..Fr...Yy. [63 4f 22 ba b1 35 9c 00 46 72 a6 9c bb 59 79 a1]
0064: ..L....._..1.>.K [d2 fe 4c 2e e4 81 eb fd 5f 8e f2 31 da 3e c0 4b]
0080: ...........(d... [1d af df 0d 0f d1 ef 1e 07 d1 9f 28 64 f4 07 d3]
0096: 0...sl.. [30 b6 ee f7 73 6c cd 85]

--- peek'd data from session #2 (104 bytes): ----------------------------------------------
0000: g.5"....Q....... [67 d9 35 22 85 90 ab eb 51 95 11 0c e6 ca 9f de]
0016: ...)... .6V&.lkF [ed 04 cb 29 e9 87 95 20 85 36 56 26 a9 6c 6b 46]
0032: ...m).V....JS... [ce b2 d7 6d 29 bb 56 fc 8e 89 a2 4a 53 a9 02 19]
0048: .w1........kY... [a1 77 31 a1 fb f8 b7 94 ee e0 d3 6b 59 ea cc ae]
0064: ...~..[..vZ..... [e3 e8 f2 7e 2e 89 5b c4 82 76 5a da ff b6 ae 91]
0080: ......7.0Z..6g.J [8a cb c8 fc eb e1 37 8e 30 5a e5 b8 36 67 c7 4a]
0096: '...qJS. [27 da b8 8f 71 4a 53 ef]

--- peek'd data from session #3 (140 bytes): -------------------------------------------------
0000: ...u.d.E..>a.... [04 c3 b1 75 e5 64 d1 45 9e b0 3e 61 81 e9 9b b7]
0016: ..\.....n..D..e. [e4 a2 5c b5 9e da a9 b9 6e 96 b7 44 12 bd 65 d9]
0032: .|(Jp..,k.....r' [c0 7c 28 4a 70 15 90 2c 6b 01 02 1a e6 d1 72 27]
0048: ..%..R]E:...N.CU [0b 8c 25 eb cd 52 5d 45 3a c4 12 f2 4e 11 43 55]
0064: gix$...d:.m..Ps1 [67 69 78 24 a1 e9 85 64 3a d5 6d 91 1a 50 73 31]
0080: Z.]...8#...q..AW [5a ca 5d db 1d 1d 38 23 0e 05 99 71 98 d8 41 57]
0096: ..]....U.7...J.? [ee 86 5d d1 0c b8 ce 55 f6 37 b5 1c 0f 4a b2 3f]
0112: ...10.......h(.* [17 15 ee 31 30 ea ee e0 b9 07 d1 c9 68 28 83 2a]
0128: ....>..g9... [be c2 e4 f9 3e e2 ea 67 39 0f b2 8c]

最佳答案

正确关闭 SSH channel 涉及的步骤不仅仅是在一侧“关闭它”。

<小时/>

首先,libssh2_channel_close() 的文档说它发送“一个 SSH_MSG_CLOSE 数据包到远程主机,作为不会向其发送进一步数据的指令”,这是可以的,但“远程主机仍可能发送数据返回,直到它发送自己的关闭消息作为响应”。

因此,该命令后面应该跟着 libssh2_channel_wait_closed() ,它处理其余的通信“直到远程主机关闭指定 channel ”。

<小时/>

此外,如所述在评论 this libssh2 commit ,“RFC 4254 中明确允许发送不带 channel EOF 的 SSH_MSG_CHANNEL_CLOSE,但当 channel 在 EOF 之前关闭时,某些不符合要求的服务器将挂起或超时”。

从而执行 libssh2_channel_send_eof() 的另一个组合和 libssh2_channel_wait_eof()为了兼容性,关闭操作本身可能也是必要的。

自 libssh2 版本 1.2.5(2010 年 4 月 13 日)起,由于 that commit mentioned earlier ,libssh2 应该在关闭时自动发送 EOF(如果尚未发送)。

<小时/>

libssh2 本身有一些示例(例如 scp_write.c ),它们显式地执行闭包,如下所示:

libssh2_channel_send_eof(channel);
libssh2_channel_wait_eof(channel);
libssh2_channel_wait_closed(channel);
libssh2_channel_free(channel);
<小时/>

(当然,对于非阻塞套接字,只要返回LIBSSH2_ERROR_EAGAIN,上述所有函数都只需调用多次即可。)

关于c - libssh2:如何处理来自 ssh 服务器的未经请求的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23257210/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com