客户端/服务器聊天室:处理意外断开连接

时间:2014-12-23 12:57:25

标签: c sockets server file-descriptor

我在C中写了一个服务器 - 客户端聊天室。

服务器为每个到客户端的新连接创建一个新的pthread,这个pthread等待接收消息,并将此消息发送给所有其他客户端(使用所有文件描述符的数组)。如果客户想要退出,他会通知服务器,他将终止pthread并从数组中删除文件描述符

这很好用!但是:

如果客户端断开连接意外,例如关闭终端,服务器不会从数组中删除文件描述符,而当其他客户端想要发送消息时我发送错误,因为pthread尝试发送发送到fd的消息不再是<\ t>连接

现在我的问题:

在发送邮件之前,如何测试客户端套接字的文件描述符是否仍然有效?

我的代码部分(来自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");
                 }
        }
}

2 个答案:

答案 0 :(得分:2)

没有独立的api来检查套接字是否已关闭。只是尝试将数据发送到该套接字。

如果您写入已关闭的套接字,

send将返回-1。 errno将适当设置。我猜你可能会EBADFECONNRESET。检查(Check connection open or closed ?(in C in Linux))和(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
                 }
        }
}

答案 1 :(得分:2)

检查recv()的返回值。

如果用户异常终止,则返回值应为零0.

基于此,您可以轻松关闭fd。

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