سؤال

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?

هل كانت مفيدة؟

المحلول

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.

نصائح أخرى

In a Windows environment, fgets is a "blocking" call. Thus, the thread that issues it iwll wait until it has some input.

Not a problem, as long as, fgets enters into an "Alertable Wait" so that the waiting I/O can be cancelled by an ExitThread(0) statement.

Again, in Windows the way to have an ExitThread(0) statement get issued in a thread that is in a wait is to schedule an APC (i.e. QueueUserAPC()) for the thread and have that scheduled method issue the ExitThread() statement.

I just did this for some code I'm writing. I know that an APC will cause a thread to exit, if that thread has issued an alterable wait. I don't know if fgets does this in Windows, that is something you will need to figure out. If not then use an I/O statement that does. Note. In Windows your code can issue an Alertable wait with WaitSingleObjectEx() on the handle of an object when the handle is signaled when I/O is available for the object.

Do an internet search on "MSDN APC" and you will find all kinds of documentation from Microsoft about this.

Pthreads? Use pthread_kill to send a SIGHUP. This will cause fgets to quit with errno set to EINTR. Send it from thread A before it exits to thread B. You might have to play with the signal handlers and masks via pthread_sigmask and sigaction, depending on how fancy you want to get.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top