select :
typedef struct Client{
int fd;
char name[NAME_LEN];
struct sockaddr_in addr;
}Client;
Client *pcls = NULL;
size_t size = INIT_SIZE;
size_t cnt = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int addClient(int fd,char *name,struct sockaddr_in addr){
if(pcls == NULL){
pcls = malloc(sizeof(Client)*5);
}
if(cnt >= size){
pcls = realloc(pcls,sizeof(Client)*2*size);
size = 2*size;
}
if(pcls == NULL){
//perror("malloc or realloc");
return -1;
}
pthread_mutex_lock(&mutex);
pcls[cnt].fd = fd;
strcpy(pcls[cnt].name,name);
pcls[cnt].addr = addr;
cnt++;
pthread_mutex_unlock(&mutex);
}
void broadcast(int fd,char *msg){
int i = 0;
for(i = 0;i<cnt;i++){
if(pcls[i].fd != fd)
send(pcls[i].fd,msg,strlen(msg)+1,0);
}
}
void delClient(int fd){
int i = 0;
for(;i<cnt;i++){
if(fd == pcls[i].fd){
pthread_mutex_lock(&mutex);
pcls[i] = pcls[cnt-1];
--cnt;
pthread_mutex_unlock(&mutex);
return;
}
}
}
void *pthread_run(void *arg){//要接收所有客户端的消息 并转发给其它客户端
int maxfd = 0;
fd_set fds;
while(true){
FD_ZERO(&fds);
int i = 0;
for(;i<cnt;i++){//把所有的文件描述符都加到 fds 集合中
FD_SET(pcls[i].fd,&fds);
if(pcls[i].fd > maxfd){
maxfd = pcls[i].fd;
}
}
struct timeval t = {0,0};
int ret = select(maxfd+1,&fds,NULL,NULL,&t);
if(ret < 0){//不可读的文件描述符会从集合中删除
continue;
}
for(i=0;ret>0&&i<cnt;i++){//ret个文件描述符可读
if(FD_ISSET(pcls[i].fd,&fds)!=0){
char buff[MSG_LEN] = {};
strcpy(buff,pcls[i].name);
strcat(buff," 说:");
int rn = recv(pcls[i].fd,buff+strlen(buff),MSG_LEN-strlen(buff),0);
--ret;
if(rn <= 0){
strcpy(buff,pcls[i].name);
strcat(buff," 退出群聊!");
broadcast(pcls[i].fd,buff);
delClient(pcls[i].fd);
--i;
continue;
}
broadcast(pcls[i].fd