Search code examples
cfgets

How to break out of fgets?


I am writing a simple instant messaging client & server to get the handle of socket programming.

My client has two threads:

  • Thread A has a streaming socket connection with the server and performs a readline in a loop, printing out lines of text it receives from the server. If the readline returns EOF, the loop exits.
  • Thread B listens to keyboard input from the user using fgets in a loop. When the user presses enter, it sends the line to the server (so it can forward it to the other client).

When a user presses Ctrl-D, the client sends a special message to the server saying "the client wants to disconnect" at which point the server closes the connection file descriptor for that user. This causes thread A to exit the loop since the readline function returns EOF. Thread A then closes the connection file descriptor and completes.

Meanwhile, thread B is still listening to keyboard input from the user until they hit enter. Ideally, the fgets would break early and let the user know that the other client disconnected.

Is there anyway to do or do I need to use a different input function or library?


Solution

  • Firstly, if you are trying to write socket functions, do not use fgets() or anything else that uses buffered IO, otherwise known as a FILE *. Instead use file descriptors (fd). Generally, every libc function beginning with 'f' is to be avoided. You want read and write.

    Secondly, you want to read up on asynchronous I/O with select(), rather than work out how to 'break out' of fgets().

    Thirdly, I could give you a tutorial here, or I could tell you to google, or look at http://en.wikipedia.org/wiki/Asynchronous_I/O but really what you want to find is a copy of Stephens (from memory "Advanced Programming in the Unix Environment" is what you want but really you should buy all of them and tape them to your body whilst you sleep in the hope of learning by osmosis).

    Fourthly, I know you said you wanted to do this with threads. You can kill a thread with pthread_cancel() if you really want to do that, and restart it. Don't. Do it properly. You don't need threads.