我在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");
}
}
}
答案 0 :(得分:2)
没有独立的api来检查套接字是否已关闭。只是尝试将数据发送到该套接字。
如果您写入已关闭的套接字, send
将返回-1。 errno
将适当设置。我猜你可能会EBADF
或ECONNRESET
。检查(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);