Windows 下以非阻塞方式读取标准输入
来源:互联网 发布:java io继承图 编辑:程序博客网 时间:2024/05/17 02:15
转自:http://blog.codingnow.com/2006/08/nbstdin.html
最近遇到一个小问题,游戏的 client 在开发调试阶段需要接收控制台的输入指令。这个需求其实一直都有,只不过以前是自己写的控制台,那样反而好控制一些。使用 Windows 标准控制台也不是第一次,但是这个输入问题都没有好好的解决。这次又碰到这个问题,决定找个好点的解决方案。
读取标准输入的 C 函数,像 scanf , gets 这些都是阻塞方式的。一经调用,程序就塞在那里不动了。起初的想法是,既然控制台输入就是一个标准输入文件,那么把这个文件修改成非阻塞模式就可以了。google 了一下,似乎 windows 下并没有 fcntl 或是 ioctl 这样的东西可以修改 stdin 为非阻塞模式。或许有别的 windows API 吧,没精力去查。
比较丑陋的方法是用 _kbhit 检测键盘输入,这个方法不太符合我的审美观。想了一下,觉得还是另外开个线程清爽一点。反正是调试用,虽然从资源占用与效率角度看不太美妙,姑且也可以凑合了。
以下代码可以工作 :)
#include <windows.h>#include <process.h>#include <stdio.h>#define BUFFER_MAX 1024char g_nbstdin_buffer[2][BUFFER_MAX];HANDLE g_input[2];HANDLE g_process[2];DWORD WINAPI console_input(LPVOID lpParameter){ for (;;) { int i; for (i=0;i<2;i++) { fgets(g_nbstdin_buffer[i],BUFFER_MAX,stdin); SetEvent(g_input[i]); WaitForSingleObject(g_process[i],INFINITE); } } return 0;}void create_nbstdin(){ int i; DWORD tid; CreateThread(NULL,1024,&console_input,0,0,&tid); for (i=0;i<2;i++) { g_input[i]=CreateEvent(NULL,FALSE,FALSE,NULL); g_process[i]=CreateEvent(NULL,FALSE,FALSE,NULL); g_nbstdin_buffer[i][0]='\0'; }}const char* nbstdin(){ DWORD n=WaitForMultipleObjects(2,g_input,FALSE,0); if (n==WAIT_OBJECT_0 || n==WAIT_OBJECT_0+1) { n=n-WAIT_OBJECT_0; SetEvent(g_process[n]); return g_nbstdin_buffer[n]; } else { return 0; }}void main(){ create_nbstdin(); for (;;) { const char *line=nbstdin(); if (line) { printf(">%s",line); } else { Sleep(0); } }}
这个程序会用一个额外的线程去读取 stdin ,我实现了一个叫做 nbstdin() 的函数,其作用有点像 gets() 。但这个函数是非阻塞的,如果控制台没有新的行输入,它会返回一个空指针。
这个程序用了两个输入 buffer 乒乓切换,这样做可以避免在两次调用 nbstdin() 之间对输入 buffer 的处理被读线程破坏掉。
程序结束的时候并没有释放创建出来的 Event 也没有主动关闭读输入的子线程,我觉得这样做更简洁,该 os 处理的事情留给 os 吧 :)
- Windows 下以非阻塞方式读取标准输入
- 非阻塞方式下Socket读取数据的一个例子
- 非阻塞方式下Socket读取数据的一个例子
- 非阻塞方式下Socket读取数据的一个例子
- 非阻塞方式下Socket读取数据的一个例子
- 非阻塞方式下Socket读取数据的一个例子
- 非阻塞方式下Socket读取数据的一个例子
- 非阻塞方式下Socket读取数据的一个例子
- 非阻塞方式下Socket读取数据的一个例子
- 非阻塞方式下Socket读取数据的一个例子
- Windows下使用socket,连接之前用非阻塞方式,连接成功后用阻塞方式
- socket阻塞与非阻塞 windows下
- php读取标准输入的方式
- 像操作普通文件一样操作FIFO --- 非阻塞方式打开,阻塞方式读取
- VC下CSocket非阻塞方式下的连接框架
- VC下CSocket非阻塞方式下的连接框架
- Linux下非阻塞读取键值的实现
- SOCKET 非阻塞方式
- 以XMLHttpRequest方式填入DataGrid
- linux如何清空终端内容
- 驴与农夫的故事
- 直接拿来用!最火的Android开源项目(一)
- [工作问题总结]支持IE 6 7 8 9 上下固定 中间自适应
- Windows 下以非阻塞方式读取标准输入
- word生成目录右对齐
- C# Winform 按ESC关闭窗体
- Java bubble sort
- PHP的预定义常量
- LISP 8.7.1 堵住漏洞1——随机end值的漏洞及调用顺序漏洞
- 直接拿来用!最火的Android开源项目(二)
- 【组件修改】winform某个tabcontrol控件的修改--加上关闭按钮
- [.NET随笔系列一].NET学习路线