问题
So, i am trying to make a c++ WinSock2 chatter, just for learning. It is a console application and i want to take user input (for sending to the counterpart), but i still want to be able to recive. (so you can write a message while still being able to recive one)...
When using cin >> input;
the program "pauses" until the user has enterd something, that way it is "turn based" (one user writes something and sends it, then the other user writes something and sends it).
Is there a way to make the user be able to write something WHILE the recive stuff is still running? (Preferably something else than multi threading)
回答1:
What about checking if buffer isn't empty? But code wouldn't be really portable then, because you need to make some system calls as I know. See this.
But maybe you can do it with some C code, I'll do some research and update my answer.
UPD: Ok, I did it. What you need is select function.
It could wait till stdin
is ready for read, and that's what we need.
But looks like it don't work with C++ streams, so you need to use only C code for reading.
Let's jump to definition:int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
Ok, we need to check only read buffer, so writefds
and errorfds
could be NULL
. And we need to check only stdin
, so nfds
is 1
(number of fds
es)
What about timeout? It's should be 0
, so we need to initialize variable struct timeval timeout
and set seconds and nanoseconds to 0 by timeout.tv_sec = 0
and timeout.tv_usec = 0
.
So, only readfds
left. It's pretty simple too: we need to initialize variable, "zero" it, and add stdin
.
It can be done with fd_set readfds
, FD_ZERO(&readfds)
and FD_SET(STDIN_FILENO, &readfds)
.
Okay, final step: function call. It should be select(1, &readfds, NULL, NULL, &timeout)
.
This would return 0
if input buffer is empty and 1
if it's not.
UPD2: Looks like it's not C++ streams, something strange happens and it breaks when buffer is empty at very first call. I'll try to catch the problem.
UPD3: Ok, Now I figured it out. Looks like you can use select
with C++ streams.
Select
has VERY strange (IMHO) feature: it resets readfds
. I'm not sure how to prevent It from doing this, so I just used one more fd_set
variable to hold it, so you need to add fd_set savefds = readfds
after readfds
initialization, and readfds = savefds
after each call. That's awful solution, but I don't know how could I improve it.
So code is:
Initialization:
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
fd_set savefds = readfds;
Timeout initialization:
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
And usage:
if (select(1, &readfds, NULL, NULL, &timeout)) {
cin >> input;
send(input);
}
readfds = savefds;
UPD4: Don't forget to include unistd.h
and cstdlib
来源:https://stackoverflow.com/questions/34479795/make-c-not-wait-for-user-input