* implementation details of using poll ** client's use of poll: STDIN_FILENO, server soc struct pollfd fds[2]; fds[0].fd = STDIN_FILENO; fds[0].events = POLLIN; fds[1].fd = server_soc; fds[1].events = POLLIN; int ret = poll(fds, 2, -1); //< poll will block until one of the fds is // ready to read _or_ poll is interrupted if ( ret < 0 ) { if ( errno != EINTR ) { // handle the error case } // if interrupted, just return to the top of the loop } else { if ( fds[0].revents & POLLIN ) { // handle keyboard input } if ( fds[1].revents & POLLIN ) { // handle message from server } if ( fds[1].revents & POLLHUP ) { // handle connection close } } ** server's use of poll: client socs, listening soc #define MAX_CLIENTS 9 int num_clients = ?; //< a variable tracking the current total client count struct pollfd fds[num_clients+1]; fds[0].fd = listening_soc; fds[0].events = POLLIN; int i; for ( i=1; i<=num_clients; i++) { fds[i].fd = clients[i-1].fd; fds[i].events = POLLIN; } int ret = poll(fds, (num_clients+1), -1); if ( ret < 0 ) { // handle EINTR and other errors } else { if ( fds[0].revents & POLLIN ) { // accept a new client connect } // iterate over the pollfd array to check for read ready client FDs // for each read-ready client, handle the message } * wrapping fds in FILE* with fdopen FILE *server_stream = fdopen(server_soc, "r+"); 1. call fflush after _every_ write operation 2. or just tell stdio to make it line buffered setlinebuf(server_stream); 3. use dprintf instead of fprintf * color requirements ** wb example allows the client to control the color, sspc doesn't do that ** color it up to the server, it can be a simple static array of color/bold options * server and client in the makefile for multiple programs in a single makefile CFLAGS = -Wall -g LDFLAGS = -l ncurses all: sspc ssps ssps: ssps.o colorlib.o socklib.o otherfile.o sspc: sspc.o colorlib.o socklib.o anotherfile.o colorlib.h: ssps.o sspc.o socklib.h: ssps.o sspc.o otherfile.h: ssps.o anotherfile.h: sspc.o * header file protections a header file should provide the external interface to a _single_ source file client.h #ifndef _CLIENT_H_ #define _CLIENT_H_ // interface definitions #endif server.h #ifndef _SERVER_H_ #define _SERVER_H_ #include "client.h" // interface definitions #endif * thread safety check the man page and standards page for indications of thread safety no mention in the standards page generally means it's OK * testing in the typescript clean build and valgrind are enough if curses shows internally allocated memory exit_curses(); * handling threads at exit memory error, signal, exit ... all cause the whole program to shut down if the main thread doesn't care about child thread status, you can just create the child thread detached else pthread_join is like wait, use it if you need to synchronize shutdown of all the threads * arrays in structs