我正在关注如何编写基本SSH客户端的教程http://api.libssh.org/master/libssh_tutor_shell.html。
我不希望ENTER键在(本地)终端中作为换行符回显。此外,我希望输入在准备好后立即读取和发送,而不是在按下ENTER后。
使用下面的代码,我尝试完成此任务。
然而,问题在于,在客户终端中,每当按下一个键时,在下一次按键之后首先显示该字符。这种行为的原因是什么?此功能确定是否按下了某个键:
int kbhit()
{
struct timeval tv = {0L, 0L};
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv);
}
从/向服务器读取/发送数据:
struct termios term_attr;
struct termios old_attr;
tcgetattr(STDIN_FILENO, &old_attr);
cfmakeraw(&term_attr);
tcsetattr(STDIN_FILENO, TCSANOW, &term_attr);
while (ssh_channel_is_open(channel) && !ssh_channel_is_eof(channel))
{
nbytes = ssh_channel_read_nonblocking(channel, buff, sizeof(buff), 0);
if (nbytes < 0)
{
return SSH_ERROR;
}
if (nbytes > 0)
{
nwritten = write(1, buff, nbytes);
if (nwritten != nbytes)
{
return SSH_ERROR;
}
}
if (!kbhit)
{
usleep(5000L);
continue;
}
nbytes = read(0, buff, sizeof(buff));
if (nbytes < 0)
{
return SSH_ERROR;
}
if (nbytes > 0)
{
nwritten = ssh_channel_write(channel, buff, nbytes);
if (nwritten != nbytes)
{
return SSH_ERROR;
}
}
}
tcsetattr(STDIN_FILENO, TCSANOW, &old_attr);
答案 0 :(得分:0)
您的程序将所有时间都用在read
函数中。因此,在敲击密钥之后,它永远不会调用ssh_channel_read_nonblocking
。
这是流程:
if (!kbhit)
为真(因为kbhit
不为NULL),我们会转到read
。read
被阻止,我们无法读取它。ssh_channel_read_nonblocking
,获取回音并回显它。也许你应该调用kbhit
函数而不是测试函数指针是否为假。