我有一个用 C 编写的非常简单的 TCP 服务器。它无限期地运行,等待连接。在 Windows 上,我使用 select 检查套接字上的活动,如果没有活动,我有以下代码允许我通过按键盘上的“q”退出:

if( kbhit() ) {
   char c = getch();
   if( c == 'q' ) break;
}

这在 unix 上不起作用,因为 kbhit 不存在并且 getch 工作方式不同。我找到了一些 示例代码 使用 tcsetattr 更改终端设置并允许逐个字符输入。调用 init 函数后,我打开 /dev/stdin (使用 O_NONBLOCK)并读取一个字符,但是 read( f, &c, 1 ) 阻止直到击中角色。

我想我可以生成一个单独的线程并有 无限期地等待,然后在用户点击“q”时向第一个线程发出信号,但这似乎有点严厉。当然有更简单的方法吗?

有帮助吗?

解决方案

将 stdin 添加到选择句柄列表中,如果它有数据,则调用 read 从中读取一个字符。

其他提示

相反,添加“f”

read( f, &c, 1 )

选择通话。当 f 准备好读取时,一个字符已被按下,read() 不会阻塞。

在 Unix 中,无论是在系统控制台还是在 X 终端窗口中,键盘 I/O 都通过虚拟终端。如今,设备 /dev/tty 是访问进程控制终端的常用方法。除打开/关闭/读/写之外的设备操作均由该特定设备的 ioctl(2) 系统调用处理。你想做的事情的总体思路是

打开控制终端(可能是也可能不是标准输入)

更改该终端上的操作模式以返回,而无需等待整行输入(这是正常的默认值)

继续程序的其余部分,知道从该终端(可能是标准输入)读取可能会返回部分行甚至零字符,而不会出现错误或终止条件。


有关如何执行第二步的详细答案可以在 C 编程常见问题解答. 。他们还指出这是一个操作系统问题,而不是语言问题。它们提供了九种可能性,但与这个问题相关的三个主要可能性是

  1. 使用curses(3)库
  2. 旧的 BSD 风格系统,使用 sgttyb 设置 CBREAK 或 RAW
  3. Posix 或旧的 System V 风格系统,使用 TCGETAW/TCSETAW 将 c_cc[VMIN] 设置为 1,将 c_cc[VTIME] 设置为 0。

遵循 C FAQ 中的一些参考文献可能会导致 本页 kbhit 代码片段.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top