Win32 - 从标准输入读取超时
我正在尝试做一些我认为应该很简单的事情:从标准输入进行阻塞读取,但如果没有数据可用,则在指定的时间间隔后超时.
I'm trying to do something which I think should be simple: do a blocking read from standard input, but timing out after a specified interval if no data is available.
在 Unix 世界中,使用 select()
会很简单,但这在 Windows 中不起作用,因为 stdin
不是套接字.在不创建额外线程等的情况下,下一个最简单的选择是什么?
In the Unix world this would be simple with select()
but that doesn't work in Windows because stdin
isn't a socket. What's the next simplest option without creating extra threads etc?
我使用的是面向 Win32 环境的 Visual C++.
I'm using visual C++ targeting a Win32 environment.
到目前为止我已经尝试过:
so far I have tried:
使用
select
(如果输入不是套接字则不起作用)
using
select
(doesn't work if the input is not a socket)
使用WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE))
.- 雷米的第一个建议.如果标准输入是控制台,这似乎总是在您调用它时立即返回(其他人报告了同样的问题)
using WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE))
. - Remy's first suggestion. This always seems to return immediately when you call it if the standard input is a console (others have reported the same problem)
使用重叠 IO 并执行 WaitForSingleObject
(Remy 的第三个建议).在这种情况下,当输入来自控制台时,读取似乎总是阻塞 - 似乎 stdin
不支持异步 I/O.
using overlapped IO and doing a WaitForSingleObject
(Remy's third suggestion). In this case the read always seems to block when the input is coming from a console - it seems that stdin
does not support asynchronous I/O.
目前我在想我唯一剩下的选择是创建一个线程,该线程将执行阻塞读取,然后发出一个事件信号,然后有另一个线程等待该事件超时.
At the moment I'm thinking my only remaining option is to create a thread which will do a blocking read and then signal an event, and then have another thread which waits for the event with a timeout.
推荐答案
我不得不解决一个类似的问题.在 Windows 上,它不像 Linux 那样容易或明显.然而,这是可能的.诀窍是 Windows 将控制台事件放在控制台输入事件队列中.您必须过滤掉您不关心的事件,只处理您真正关心的事件(例如按键).
I had to solve a similar problem. On Windows it is not as easy or obvious as Linux. It is, however, possible. The trick is that Windows places console events in the console input event queue. You've got to filter out the events you don't care about and only process those events you do care about (like key presses).
进一步阅读:请参阅 Win32 控制台文档
以下是一些基于套接字和标准输入多路复用器的主要调试示例代码:
Here is some mostly-debugged sample code based on a socket and stdin multiplexer I was working on:
void ProcessStdin(void)
{
INPUT_RECORD record;
DWORD numRead;
if(!ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &record, 1, &numRead)) {
// hmm handle this error somehow...
return;
}
if(record.EventType != KEY_EVENT) {
// don't care about other console events
return;
}
if(!record.Event.KeyEvent.bKeyDown) {
// really only care about keydown
return;
}
// if you're setup for ASCII, process this:
//record.Event.KeyEvent.uChar.AsciiChar
} // end ProcessStdin
int main(char argc, char* argv[])
{
HANDLE eventHandles[] = {
GetStdHandle(STD_INPUT_HANDLE)
// ... add more handles and/or sockets here
};
DWORD result = WSAWaitForMultipleEvents(sizeof(eventHandles)/sizeof(eventHandle[0]),
&eventHandles[0],
FALSE,
1000,
TRUE
);
switch(result) {
case WSA_WAIT_TIMEOUT: // no I/O going on right now
break;
case WSA_WAIT_EVENT_0 + 0: // stdin at array index 0
ProcessStdin();
break;
case WSA_WAIT_EVENT_0 + 1: // handle/socket at array index 1
break;
case WSA_WAIT_EVENT_0 + 2: // ... and so on
break;
default: // handle the other possible conditions
break;
} // end switch result
}
相关文章