Marius Küpper
Marius Küpper

Reputation: 267

Client/server chatroom: Handle unexpected disconnect

I wrote in C a server - client chatroom.

The server creates a new pthread for every new connection to a client, this pthread waits for a message to receive, and sends this message to all the other clients (using a array of all the file descriptors). If a client wants to quit he informs the server and he will terminate the pthread and delete the file descriptor from the array

This works fine !, but:

if a client disconnects unexpected, by closing the terminal for example, the server won't delete the file descriptor from the array and when an other client wants to send a message i have an error because the pthread tries to send the message to a fd which isn't a connection any more

Now my question:

How can in test if the file descriptor of a client's socket is still active before i send a message ?

the part of my code (from the pthread):

for(i=0; i<*p_Nbr_Clients; i++){ // send the message to all the other clients
        if (fd_array[i] != fd){ // <- i want to test the fd here
                 if ( send(fd_array[i], msg, strlen(msg), 0) == -1 ){
                     perror("Serveur: send");
                 }
        }
}

Upvotes: 0

Views: 1095

Answers (2)

D3Hunter
D3Hunter

Reputation: 1349

There is no standalone api to check whether socket is closed. Just try to send data to that socket.

send will return -1 if you write to a closed socket. and errno will be set to appropriately. You may got EBADF or ECONNRESET i guess. Check (Check connection open or closed ?(in C in Linux)) and (How to find out if a socket is closed)

for(i=0; i<*p_Nbr_Clients; i++){ // send the message to all the other clients
        if (fd_array[i] != fd){ // <- i want to test the fd here
                 if ( send(fd_array[i], msg, strlen(msg), 0) == -1 ){
                     //perror("Serveur: send");
                     // something wrong, check errno to see more detail
                     // you need to include <errno.h> to use errno
                     close(fd_array[i]);
                     fd_array[i] = -1;// or something you define as not open
                 }
        }
}

Upvotes: 2

Chandru
Chandru

Reputation: 1334

Check the return value of the recv().

If the user terminated abnormally then return value should be zero 0.

Based on that you can close fd easily.

if(recv(fd,buffer,length,flag) == 0)
      close(fd);

Upvotes: 2

Related Questions