Sign in to follow this  
Telastyn

Non-blocking stdin read on win32

Recommended Posts

I am currently in the process of porting the server side of my current project over to win32 from unix-world. Part of the app allows for someone at the console to enter in simple commands via keyboard. On the unix side, this was fairly simple. I added 0 to the read fdset, and then read(0,buf,bufsize) when select said there was stuff to read. Being on a line buffered terminal made this even nicer. Windows though kind of complicates matters. select() doesn't seem to like trying to select over non-socket file descriptors, which wouldn't really suprise me. The fix I tried was setting select() to non-blocking, and placing the console read in the main while(1) loop. read() [or _read on win32] blocks though, so I went looking into the STL; which I'm admittedly not very familiar with. cin.readsome() appears to do what I'd like, which is read what data is available, and return ASAP. It doesn't though. Type-echo doesn't even seem to work, and the keystrokes sent to the app are instead sent to the CLI after the app closes. So what gives? Am I just ignorant of a little STL trick, or am I barking up the wrong tree? What's the proper way on win32 to read keystrokes from the console without blocking the rest of the app?

Share this post


Link to post
Share on other sites

Interesting problem :)

I scratched my head on this for quite a bit myself.

but I managed to get a solution (well, I think it is)

from what I can tell, you want a way to tell if someone has typed something into the console, but that doesn't block..
I'm not a *nix person, so I would have never thought of using sockets??!

well... anyway this is the test code



...
#include <conio.h>


int main(int argc, char* argv[])
{

while (true)
{
int i=_kbhit();

while (i--)
{
char msg[256];

cin.getline(msg,256);

printf("****\n");
printf(msg);
printf("\n****\n");
}


Sleep(1000);
printf("beep\n");
}
}




seems to work. Yay for msdn.

Share this post


Link to post
Share on other sites
If all you need is byte input (i.e. char) from the keyboard, you can use _kbhit() to decide when to call _getch() or similar functions. Alternatively - and preferably - you can use ReadConsole() which is a Win32 API call. You can determine the console handle attached to stdin with GetStdHandle().

Share this post


Link to post
Share on other sites
Keep in mind that getch, kbhit and the rest of <conio.h> is non-standard, meaning the compiler vendor is not guaranteed to supply them. Everything in <windows.h>, OTOH, is guaranteed to be available for Win32 platforms.

And, yeah, I think ReadConsole is a better option than ReadFile.

Share this post


Link to post
Share on other sites
Hrm, unfortunately ReadConsole blocks until there's at least 1 char to read. A combination of the two [as well as fiddling with the console settings] seems to do the trick though.

Code, for anyone curious.



// Server Setup Procedures Above

#ifdef _WIN32
// set to line buffered mode.
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT);
#endif
while (1){
/* the main gameserver loop.
All connection handling, message passing and gameplay calculations will occur from here.


*/

selected=fds;
#ifdef _WIN32
if (_kbhit()){
bzero(buf,cmdlen);
ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE),buf,cmdlen-2,(unsigned long *)&rtn,0);
if (debug && rtn){ printf ("%i:%i=%s",testfd,rtn,buf); }
// damned windows.
// message() expects newline delimited.
// and the line buffered mode doesn't echo newlines...
strcat(buf,"\n");
printf("\n");
if (rtn && strstr(buf,"\n")){
message(testfd,buf,rtn);
}else{
if (debug){printf ("No newline, chucking.\n");}
}
}

#endif

// Proceed with select() and client message handling here.

}





And my appologies if anything is ugly or newb-tacular, this is my first experience with trying to make code which compiles nicely on multiple platforms, and I've never had any even semi-serious code reviewed/critiqued by others.

Now that this is complete, hopefully I can now package everything up and get something akin to a tech demo out for people to critique.

Many thanks.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this