У меня есть простая туннельная программа, которая должна одновременно блокировать стандартный ввод и сокет. В настоящее время у меня есть программа, которая выглядит следующим образом (обработка ошибок и прочее),
HANDLE host = GetStdHandle(STD_INPUT_HANDLE);
SOCKET peer = ...; // socket(), connect()...
WSAEVENT gate = WSACreateEvent();
OVERLAPPED xfer;
ZeroMemory(&xfer, sizeof(xfer));
xfer.hEvent = gate;
WSABUF pbuf = ...; // allocate memory, set size.
// start an asynchronous transfer.
WSARecv(peer, &pbuf, 1, 0, &xfer, 0);
while ( running )
{
// wait until standard input has available data or the event
// is signaled to inform that socket read operation completed.
HANDLE handles[2] = { host, gate };
const DWORD which = WaitForMultipleObjects
(2, handles, FALSE, INFINITE) - WAIT_OBJECT_0;
if (which == 0)
{
// read stuff from standard input.
ReadFile(host, ...);
// process stuff received from host.
// ...
}
if (which == 1)
{
// process stuff received from peer.
// ...
// start another asynchronous transfer.
WSARecv(peer, &pbuf, 1, 0, &xfer, 0);
}
}
Программа работает как шарм, я могу передавать вещи через эту туннельную программу без помех. Дело в том, что в нем есть небольшая ошибка.
Если я запускаю эту программу в интерактивном режиме с cmd.exe
и к клавиатуре присоединяется стандартный ввод, нажатие клавиши, которая не производит ввод (например, клавиша Ctrl
), приводит к блокировке этой программы и игнорированию данных, полученных на разъем. Мне удалось понять, что это потому, что нажатие любой клавиши сигнализирует о стандартном дескрипторе ввода, и WaitForMultipleObjects()
возвращает. Как и ожидалось, управление входит в блок if (which == 0)
и вызывает блоки ReadFile()
, потому что нет доступных входных данных.
Есть ли способ определить, сколько входных данных доступно в потоке Win32? Если это так, я мог бы использовать это, чтобы проверить, доступен ли какой-либо ввод перед вызовом ReadFile()
, чтобы избежать блокировки.
Мне известно несколько решений для определенных типов потоков (в частности, ClearCommError()
для последовательных портов и ioctlsocket(socket,FIONBIO,&count)
для сокетов), но ни одно из известных мне не работает с потоком CONIN$
.