PDA

View Full Version : non-blocking keyboard read



pppbigppp
01-16-2007, 05:14 AM
Hi,

Does anyone know which function/library I should use to be able to read a line of user input without Curse? And once I find this function, the following code structure should be able to pick up the keyboard I/O stream right?



fd_set rset;
int max_sd=highest_sd++;

while(1) {
FD_SET(0, &rset);
if( select(max_sd, &rset, NULL, NULL, NULL) < 0 ) {
//error code
}

if( FD_ISSET( 0, &rset ) {
//a line has been entered, do something useful here
} else if( FD_ISSET( other_sd, &rset) {....
} else {
//error: select() not blocking
}



Thanks

Salem
01-16-2007, 06:16 AM
Well it seems like a reasonable start, what sort of effect are you seeing compared to what you expect?

Also, how are you reading stdin when select says there is data available?

Did you use setbuf/setvbuf on stdin to make it non-blocking before doing any of this.

I'm assuming that you're on Linux (or other *IX OS with a proper implementation of select).

pppbigppp
01-16-2007, 06:46 AM
Well it seems like a reasonable start, what sort of effect are you seeing compared to what you expect?

Also, how are you reading stdin when select says there is data available?

Did you use setbuf/setvbuf on stdin to make it non-blocking before doing any of this.

I'm assuming that you're on Linux (or other *IX OS with a proper implementation of select).

I think I got it to work. I'm on linux.

I'm basically trying to demux socket IO and keyboard IO such that a user can send and receive message at the same time.

new question:
Is it possible to block persistent TCP connection until new data arrives? I'm trying to use one connection for all the message exchange between two network sockets, and I want the process to block until new data is available. select() does not seem to be able to block the socket. I dig up the man page and surely enough, select() unblock when a socket is ready for transmission, not when new data is available. Any idea?

What I have currently is this


sdTCPChild = accept(sdTCP, ...

while(1) {
FD_SET(sdTCPChild, *rset);
if( select() .... ) {
}

if( FD_ISSET( sdTCPChild, &rset) ) {
//received TCP data, read it, do something useful
//#1
}
}

What would happen is that the client would establish a connection with the server. But as soon as it sends one piece of data, the server would loop forever through #1 (bypassing select()'s blocking). It would read the data at the first cycle, then read 0 bytes from the pipe afterward.

Thanks!

Salem
01-16-2007, 07:01 AM
> select() unblock when a socket is ready for transmission, not when new data is available. Any idea?
Yes, use the correct set.
select() can operate on input, output and errors. So use the 'write' set to block on a socket until it is ready to send.

pppbigppp
01-16-2007, 07:31 AM
> select() unblock when a socket is ready for transmission, not when new data is available. Any idea?
Yes, use the correct set.
select() can operate on input, output and errors. So use the 'write' set to block on a socket until it is ready to send.

I'm trying to read from a socket.

READ->DISPLAY;
KEYBOARD->WRITE(send)

The problem is that read() blocks the first time, but for some reason it does not block anymore afterward(which is also why select does not block AFTER the first piece of data arrives). So I end up with this


bytesRead = read(sdTCPChild, recBuf, sizeof(recBuf)); //properly blocks until data comes, read non-zero bytes from socket
bytesRead = read(sdTCPChild, recBuf, sizeof(recBuf)); //does not block, read 0 bytes. ???

Salem
01-16-2007, 11:37 AM
Did you make the sockets themselves non-blocking?

pppbigppp
01-16-2007, 06:21 PM
Did you make the sockets themselves non-blocking?

I didn't do anything special to the socket. By default it blocks. The first read() works perfectly fine. I think I know what the problem is, but don't know the solution yet. My guess is that the first read() take all the bytes in the socket. Then somehow the second read() only see the EOF character in the socket. So it immediately returns with 0 bytes read. This would also explain why select() won't block. This is not the behaviour I expected though.

Here is some of the socket initiation code


//omit a bunch of error checking to save space
sdTCP = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
bind(sdTCP, (struct sockaddr *)&sad, sizeof(sad));
listen(sdTCP, QLEN);


I had another program that does network data transfer and it works. The major difference is that the program I'm working on is based on persistent TCP connection.

Salem
01-17-2007, 01:05 AM
Doesn't 0 mean the socket in question has been closed?

pppbigppp
01-17-2007, 05:54 AM
Doesn't 0 mean the socket in question has been closed?

Oh my, that was it. There is a rouge close(socket) statement in my client socket write routine(left over from the non-persistent connection design). I didn't notice it for so long cause I kept thinking its server's problem. Now everything make sense again. Select is working just fine

Thanks a bunch!

pppbigppp
01-17-2007, 06:25 AM
Follow up question:

What's the most graceful way to detect broken pipe? Currently, if either the client and the server close() its end of the pipe, select() on the other process will unblock indefinitely and so I end up with infinite loop.

Is there a function call that checks up on a file descriptor?

Salem
01-17-2007, 06:51 AM
Just a guess, but I said
select() can operate on input, output and errors.
If you put your sockets / pipes / whatever into the error set as well, then you should get information as to when the unexpected happens.