int main(void) { void myhandle(int signum); signal(SIGINT,myhandle); serv_fd = udp_link(); H = (struct servmsg *)malloc(sizeof(struct servmsg)); H->next = NULL; static struct servmsg *H_recv; H_recv = H; socklen_t addrlen= -1; int ret = -1; int on = 1; static pthread_t tid1 = -1; bzero(&self_addr,sizeof(struct sockaddr)); /*设置服务器IP地址和端口*/ self_addr.sin_family = AF_INET; self_addr.sin_port = htons(SERVER_PORT); self_addr.sin_addr.s_addr = inet_addr(SEVER_IP); ret = setsockopt(serv_fd,SOL_SOCKET,SO_REUSEADDR,(void *)&on,sizeof(on)); if(ret < 0){ perror("setsockopt to SO_REUSEADDR"); exit(1); } if(bind(serv_fd,(struct sockaddr *)&self_addr,sizeof(struct sockaddr)) < 0){ perror("bind"); exit(1); } printf("*******欢迎使用********\n"); printf("服务器正在运行……\n"); /*创建解析数据包的线程*/ if(pthread_create(&tid1, NULL, pthread_func,NULL ) < 0){ perror("pthread_create"); exit(1); } pthread_detach(tid1); addrlen = sizeof(struct sockaddr_in); while(1) { bzero(&cli_msgbuf,sizeof(struct msg)); ret = recvfrom(serv_fd,&cli_msgbuf,sizeof(cli_msgbuf),0,(struct sockaddr *)&cli_addr,&addrlen); if(ret < 0) { perror("recvfrom"); exit(1); } printf("有新消息发送到服务器\n"); /*把收到的消息放入链表等待解析*/ insert(&H_recv,cli_msgbuf,cli_addr);//H_recv每次改变,将消息每次插入至链表末尾 } return 0; }
/*转发群聊消息至广播地址(客户端另开辟了一条接收群聊消息的线程)*/ void chat_toall( ) { // int msglen = -1; // socklen_t addrlen = -1; // int num = -1; // struct sockaddr_in msgbuf_tmp; //组播 // printf("group_fd:%d\n",group_fd); // bzero(&msgbuf_tmp,sizeof(struct sockaddr_in)); // msgbuf_tmp.sin_family = AF_INET; // msgbuf_tmp.sin_port = htons(GROUP_PORT);// // /* 设置发送组播消息的源主机的地址信息 */ // msgbuf_tmp.sin_addr.s_addr = inet_addr(GROUP_IP); // struct msg buf; // buf = H->recvmsg; // msglen = sizeof(char)+20+20+strlen(buf.data); // addrlen = sizeof(msgbuf_tmp); // num = sendto(group_fd,&buf,msglen,0,(struct sockaddr *)&msg,buf_tmp,addrlen); // if(num < 0){ // perror("sendto"); // exit(1); // } // // H->recvmsg.data[num - sizeof(H->recvmsg.type)-sizeof(H->recvmsg.self_name)-sizeof(H->recvmsg.dst_name)] = '\0'; // printf("num:%d\n",num); // printf("self_name:%s\n",buf.self_name); // printf("data:%s\n",buf.data); // printf("消息已发送至组播地址\n"); int group_fd; //广播套接字 int msglen ; int num; int nb = 0; int opt = 1; struct msg buf; group_fd = udp_link(); buf = H->recvmsg; //设置该套接字为广播类型, nb = setsockopt(group_fd, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt)); if(nb < 0) { perror("SO_BROADCAST:"); } struct sockaddr_in addrto; bzero(&addrto, sizeof(struct sockaddr_in)); addrto.sin_family=AF_INET; addrto.sin_addr.s_addr=htonl(INADDR_BROADCAST); addrto.sin_port=htons(6000); int nlen=sizeof(addrto); msglen = sizeof(char)+20+20+strlen(buf.data); num = sendto(group_fd,&buf,msglen,0,(struct sockaddr *)&addrto,nlen); if(num < 0){ perror("sendto"); exit(1); } // H->recvmsg.data[num - sizeof(H->recvmsg.type)-sizeof(H->recvmsg.self_name)-sizeof(H->recvmsg.dst_name)] = '\0'; printf("num:%d\n",num); printf("self_name:%s\n",buf.self_name); printf("data:%s\n",buf.data); printf("消息已发送至广播地址\n"); }
/*解析消息线程*/ void *pthread_func() { int group_fd; //组播套接字 group_fd = udp_link(); head_user = (struct user_info *)malloc(sizeof(struct user_info)); head_user->next = NULL; struct user_info *tmp; // 循环变量,用于便利在线用户链表将其发送给第一次登录的或者有刷新请求的客户端 struct servmsg *free_tmp; int ret= -1; while(1){ while(H->next != NULL){ free_tmp = H; H = H->next; //消息头,处理玩就往后移动 free(free_tmp);//将处理完的消息所占内存释放掉 free_tmp = NULL; printf("消息来自:%s IP:PORT:%s:%d\n",H->recvmsg.self_name,inet_ntoa(H->addr.sin_addr),ntohs(H->addr.sin_port)); switch(H->recvmsg.type) { case LOG_IN: printf("%s登录消息\n",H->recvmsg.self_name); send_message_to_all(H,LOGIN_TOALL); add_user(head_user,H); break; case REFRESH: printf("%s刷新消息\n",H->recvmsg.self_name); //usleep(50000); send_all_online(H->addr); break; case CHAT_PRI: printf("%s私聊消息\n",H->recvmsg.self_name); printf("目标:%s\n",H->recvmsg.dst_name); chat_private(); break; case CHAT_ALL: printf("%s群聊消息\n",H->recvmsg.self_name); send_message_to_all(H,CHAT_ALL); break; case FILE_NAME: printf("%s申请下载\n",H->recvmsg.self_name); send_dir_allfile(H->addr); break; case DOWNLOAD: printf("%s 确认下载\n",H->recvmsg.self_name); pthread_create(&tid2,NULL,download_send,(void *)&H->addr); pthread_detach(tid2); break; case UPLOAD: printf("%s上传文件\n",H->recvmsg.self_name); pthread_create(&tid3,NULL,(void *)&upload_func,NULL); pthread_detach(tid3); break; case OFFLINE: printf("%s下线\n",H->recvmsg.self_name); delete_user(H->recvmsg.self_name); break; case CREATE_GROUP: printf("%s create group\n",H->recvmsg.self_name); create_group(H); break; case JOIN_GROUP: printf("%s join group\n",H->recvmsg.self_name); join_group(H); break; case LIST_GROUP: printf("%s list group\n",H->recvmsg.self_name); list_group(H); break; case GROUP_CHAT: printf("%s group chat\n",H->recvmsg.self_name); group_chat(H); break; case GROUP_DELETE: printf("%s delete group\n",H->recvmsg.self_name); delete_group(H); break; default: printf("msg type error !\n"); break; } printf("-----------------------------------\n"); } } }