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

Popular posts from this blog

how to insert data php javascript mysql with multiple array session 2 -

multithreading - Exception in Application constructor -

windows - CertCreateCertificateContext returns CRYPT_E_ASN1_BADTAG / 8009310b -