Note that there are some explanatory texts on larger screens.

plurals
  1. POC Server stops responding when client disconnects
    primarykey
    data
    text
    <p>I have written a fairly simple C chat server with the use of pthreads. Server works without any problem, client connects to it using telnet and then clients can communicate with each other. Each client is started within its own thread. The problem arises, when any of the clients desides to disconnect. Even though i close client socket and finish its thread (which it does, or at least gdb says so) this disturbance somehow closes all communication on the server side, even though other threads are still running. After this, clients cannot communicate with each other and thus rendering server quite useless. I do not know how to fix this and i ask for your help. Thank you.</p> <p>Here is my code. I include full code for i am not certain where is my mistake</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;unistd.h&gt; #include &lt;string.h&gt; #include &lt;errno.h&gt; #include &lt;sys/types.h&gt; #include &lt;sys/socket.h&gt; #include &lt;arpa/inet.h&gt; #include &lt;pthread.h&gt; int user[30]; // sockets of connected users char names[30][20]; int user_count=0; // number of active connections int listen_sock; // main socket, recieves connections char buffer[500]; pthread_t *thready[30]; pthread_mutex_t mutex; struct arg_struct { int arg1; int arg2; }; void sending(char *text, int i) { char buffer2[504]; strcpy(buffer2, "\r\0"); strcat(buffer2, text); strcat(buffer2, "\r\0"); write(user[i], buffer2, strlen(buffer2)); } void welcome(int id) { int len; int sock; char name[20]; pthread_mutex_lock(&amp;mutex); sock = user[id]; write(sock,"\rEnter your name: ", 18); // Read returns number of characters recieved len = read(sock,name,20); // Add zero to the end of string (read doesnt do it) name[len]='\0'; while (name[len] &lt; 32) { name[len]='\0'; len--; } // snprintf(buffer,"Welcome %s!\n",name); write(sock, "Welcome\r\n", 7); strcpy(names[id], name); sending(buffer,id); pthread_mutex_unlock(&amp;mutex); } void echo(char *text) { int i; for (i=0; i&lt;user_count; i++) { sending(text, i); } } void disconnect(int id) { int i; char deadname[20]; strcpy(deadname,names[id]); sending("You have been disconnected\n",id); shutdown(user[id], SHUT_RDWR); close(user[id]); for (i=id; i&lt;user_count-1; i++) { user[i]=user[i+1]; strcpy(names[i],names[i+1]); } user_count--; sprintf(buffer,"%s has disconnected\n",deadname); echo(buffer); } void finish() { echo("Shuting down, disconnecting everyone!\n"); while (user_count &gt; 0) disconnect(user_count-1); shutdown(listen_sock, SHUT_RDWR); close(listen_sock); pthread_mutex_destroy(&amp;mutex); exit(0); } void getcomm(char *inpstr, char *comm) { /* First letter from inpstr goes to comm, and is removed from inpstr */ int wpos=0,leng; /* Splits first word from the rest of the sentence */ char *zal; zal=inpstr; leng=strlen(zal); while (*inpstr&gt;32 &amp;&amp; wpos&lt;14) { *comm=*inpstr++; comm++; wpos++; } inpstr=(char *)memmove(zal,inpstr+1,leng); *comm='\0'; } void input(int id) { } void* communication(void* par){ int sock = ((int*)par)[0]; int id = ((int*)par)[1]; free((int*)par); welcome(id); while(1){ char line[500]; char command[20]; char name2[16]; int len,sock; // 1. read line from user len=read(user[id],line,499); pthread_mutex_lock(&amp;mutex); line[len]='\0'; if (len == 0) { // User has terminated the connection continue; } while (line[len] &lt; 32) { // Remove special chars line[len]='\0'; len--; } // 2. Get first word getcomm(line,command); // 3. Recognise command and execute it len=strlen(command); if (strncmp(command,"quit",4) == 0) { disconnect(id); pthread_exit(NULL); } else if (!strncmp(command,"tell",len)) { getcomm(line,name2); sprintf(buffer,"%s tells %s: %s\n", names[id], name2, line); echo(buffer); } else if (!strncmp(command,"shut",len)) { finish(); } // 4. Unknown command else { sprintf(buffer,"%s tells %s %s\n", names[id], command, line); echo(buffer); } pthread_mutex_unlock(&amp;mutex); } } int main( int argc, char *argv[] ) { int pid; struct sockaddr_in bind_addr; struct sockaddr_in acc_addr; int size, user_id, i, sel,on; int port_number; char * eptr = NULL; fd_set readmask; pthread_mutexattr_t attr; pthread_mutexattr_init(&amp;attr); pthread_mutex_init(&amp;mutex, NULL); listen_sock = socket(AF_INET, SOCK_STREAM, 0); if (listen_sock==-1) { perror("socket()"); pthread_mutex_destroy(&amp;mutex); exit(-1); } on = 1; if (argc == 1){ perror("Please specify port number"); pthread_mutex_destroy(&amp;mutex); //exit(0); } if (argc == 2){ port_number = (int) strtol(argv[1], &amp;eptr, 10); if (*eptr != '\0'){ perror("Invalid Port Number!"); pthread_mutex_destroy(&amp;mutex); exit(-1); } } port_number = 7501; bind_addr.sin_family = AF_INET; bind_addr.sin_addr.s_addr = INADDR_ANY; bind_addr.sin_port = htons(port_number); size=sizeof(struct sockaddr_in); setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&amp;on, sizeof(on)); if (bind(listen_sock, (struct sockaddr *)&amp;bind_addr, size)==-1) { perror("bind()"); pthread_mutex_destroy(&amp;mutex); exit(-1); } listen(listen_sock, 10); while(1) { FD_ZERO(&amp;readmask); FD_SET(listen_sock, &amp;readmask); if (FD_ISSET(listen_sock, &amp;readmask)) { user_id = user_count++; int * soc = (int*)malloc(2*sizeof(int)); soc[0] = accept(listen_sock,(struct sockaddr *)&amp;acc_addr, &amp;size); soc[1] = user_id; pthread_mutex_lock(&amp;mutex); user[user_id] = soc[0]; pthread_mutex_unlock(&amp;mutex); if( ( pthread_create( &amp;thready[user_id], NULL, communication, (void*)soc ) ) &lt; 0) { perror("could not create thread"); return 1; } echo(buffer); continue; } } pthread_mutex_destroy(&amp;mutex); return 0; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload