c - NCurses chat misbehaving, blocking in select -
i wrote c application socialization network , simple room-based chat. used ncurses, sockets , basic networking stuff.
the problem function uses select() read server socket , stdin when start write message, output window freezes , shows messages other clients after hit enter.
i tried possible .. there way fix ?
i tried force nocbreak().it works okay if that, when write message, echoing disabled , nothing shows in input window type, though message there "invisible".
here code :
ssize_t safeprefread(int sock, void *buffer) { size_t length = strlen(buffer); ssize_t nbytesr = read(sock, &length, sizeof(size_t)); if (nbytesr == -1) { perror("read() error length ! exiting !\n"); exit(exit_failure); } nbytesr = read(sock, buffer, length); if (nbytesr == -1) { perror("read() error data ! exiting !\n"); exit(exit_failure); } return nbytesr; } ssize_t safeprefwrite(int sock, const void *buffer) { size_t length = strlen(buffer); ssize_t nbytesw = write(sock, &length, sizeof(size_t)); if (nbytesw == -1) { perror("write() error length ! exiting !\n"); exit(exit_failure); } nbytesw = write(sock, buffer, length); if (nbytesw == -1) { perror("write() error data ! exiting !\n"); exit(exit_failure); } return nbytesw; } void activechat(int sc, const char *currentuser, const char *room) { char inmesg[513], outmesg[513]; char user[33]; int winrows, wincols; window *winput, *woutput; initscr(); nocbreak(); getmaxyx(stdscr, winrows, wincols); winput = newwin(1, wincols, winrows - 1, 0); woutput = newwin(winrows - 1, wincols, 0, 0); keypad(winput, true); scrollok(woutput, true); wrefresh(woutput); wrefresh(winput); fd_set all; fd_set read_fds; fd_zero(&all); fd_zero(&read_fds); fd_set(0, &all); fd_set(sc, &all); wprintw(woutput, "welcome room '%s' \n use /quitchat exit !\n!", room); wrefresh(woutput); while (true) { memcpy( &read_fds, &all, sizeof read_fds ); if (select(sc + 1, &read_fds, null, null, null) == -1) { perror("select() error or forced exit !\n"); break; } if (fd_isset(sc, &read_fds)) { memset(inmesg, 0, 513); safeprefread(sc, user); safeprefread(sc, inmesg); wprintw(woutput, "%s : %s\n", user, inmesg); wrefresh(woutput); wrefresh(winput); } if (fd_isset(0, &read_fds)) { //wgetnstr(winput, "%s", outmesg); int a, = 0; while ( < max_buf_len && (a = wgetch(winput)) != '\n') { outmesg[i] = (char)a; i++; } outmesg[i] = 0; if (outmesg[0] == 0) continue; if (strcmp(outmesg, "/quitchat") == 0) { safeprefwrite(sc, outmesg); break; } safeprefwrite(sc, outmesg); delwin(winput); winput = newwin(1, wincols, winrows - 1, 0); keypad(winput, true); wrefresh(winput); } } delwin(winput); delwin(woutput); endwin(); } -safeprefwrite , safeprefread wrappers prexied read / write , error treating -sc server socket.
le: tried using fork , threads. using fork behaving same , threads disaster, terminal messed up.
thank you.
modify while(true) loop handle 1 char @ time stdin.
which means stdin, read single char:
if char '\n' handle currently,
otherwise, append char buffer write.
always, before appending char buffer write, check buffer not full.
add code handle case buffer write full
end function sequence:
delwin(winput); delwin(woutput); endwin(); endwin(); to end both windows.
do not call endwin() during processing of socket input.
do not call endwin() when select() returns error condition
the fd_set not intrinsic size in c, use memcpy() set read_fds all. suggest:
memcpy( &read_fds, &all, sizeof read_fds ); the parameter: currentuser not used, suggest inserting line:
(void)currentuser; to eliminate compiler warning message.
for readability, , ease of understandability, suggest #define magic numbers 513 , 33 meaningful names, use meaningful names throughout code.
#define max_buf_len (513) #define max_user_len (33) this line: outmesg[i] = a; raises compiler warning, suggest:
outmesg[i] = (char)a; this line: while ( (a = wgetch(winput)) != '\n') can allow buffer outmesg[] overrun, resulting in undefined behaviour , can lead seg fault event. suggest:
while ( < max_buf_len && (a = wgetch(winput)) != '\n') suggest posting prototypes safeprefwrite() , safeprefread() functions, similar to:
void safeprefread( int, char * ); void safeprefwrite( int, char * );
Comments
Post a Comment