#include #include #include #include #include #include #include #include #include #include #include #include "head.h" #include #define h_yi_shu (1<<0) #define h_shou_gong (1<<1) #define h_yun_dong (1<<2) #define h_lv_you (1<<3) #define h_yang_sheng (1<<4) #define h_shi_ting (1<<5) #define h_xue_xi (1<<6) #define h_si_kao (1<<7) #define h_da_ban (1<<8) #define h_kai_hei (1<<9) #define h_other (1<<10) #define f_peng_you (1<<0) #define f_zhi_ji (1<<1) #define f_lian_ren (1<<2) #define f_hun_yin (1<<3) #define f_pao_you (1<<4) #define f_ji_you (1<<5) #define f_gui_mi (1<<6) #define f_yan_you (1<<7) #define f_huo_ban (1<<8) #define f_shang_ye (1<<9) #define f_other (1<<10) #define mmp_usermesg_len 10 #define group_message_len 20 //群信息的数量 #define mmp_friendadd_len (mmp_usermesg_len * sqrt(mmp_usermesg_len)) typedef struct{ struct sockaddr_in address; char ip[16]; int port; }netinfo; typedef struct{ int namlen; char name[16]; }guestinfo; typedef struct{ int mesgtype; int msglen; char message[1024]; }unitmesg; typedef struct{ int mesgtype; int namlen; char name[16]; int meslen; char message[1004]; }guestmesg; typedef struct{ int mesgtype; unsigned int o_userid; unsigned int s_regitime; unsigned int o_loghowtime; unsigned long o_logintime; unsigned long p_birthday; unsigned long s_phone; unsigned long s_identity; int p_schlen; char p_school[24]; int s_lognamlen; char s_logname[16]; int s_logpaslen; char s_logpassword[16]; int s_maillen; char s_mail[32]; int m_netnamlen; char m_netname[16]; int p_trunamlen; char p_truename[16]; char o_lateloginip[16]; char s_regiip[16]; int m_motlen; char m_motto[32]; int m_brilen; char m_brief[762]; char p_sex; unsigned char o_rank; unsigned char m_hobby; unsigned char m_chataim; unsigned char p_education; unsigned char o_status; }usermesg; typedef struct{ unsigned int youid; unsigned int meettime; char groupname[16]; char friendremark[16]; }friendmesg; singlylist *netlist=NULL; //套接字连接链表 singlylist *guestlist=NULL; //匿名用户信息链表 singlylist *grouplist=NULL; //匿名世界群、实名世界群、实名自建群1、2、3...链表的链表头 singlylist *friendlist=NULL; //实名账户下的陌生人、好友、自建好友1、2、3...链表的链表头 friendmesg *friendmm=NULL; singlylist *userlist=NULL; //实名用户信息链表 usermesg *usermm=NULL; int inittcpsocket(int port){ int sfd; sfd=socket(AF_INET,SOCK_STREAM,0); fcntl(sfd, F_SETFL, fcntl(sfd, F_GETFL, 0) | O_NONBLOCK); //设置套接字accept不阻塞 printf("control:%d\n",sfd); int on=1; setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); //端口复用 struct sockaddr_in address; address.sin_family=AF_INET; address.sin_port=htons(1209); address.sin_addr.s_addr=htonl(INADDR_ANY); bzero(address.sin_zero,sizeof(address.sin_zero)); int ret; ret=bind(sfd,(struct sockaddr *)&address,sizeof(address)); printf("bind:%d\n",ret); ret=listen(sfd,128); printf("listen:%d\n",ret); return sfd; } int breaksfd; void sigpipe(int signo){ close(breaksfd); singlylist *closeusernode=searchlistnode(userlist,breaksfd); if(closeusernode!=NULL){ closeusernode->id=-breaksfd; usermesg *userupdate = (usermesg *)(closeusernode->content); userupdate->o_loghowtime=time(NULL)-userupdate->o_logintime; userupdate->o_rank+=userupdate->o_loghowtime/60; userupdate->o_status=0; } if(searchlistnode(guestlist,breaksfd)!=NULL) deletelistnode(&guestlist,breaksfd); deletelistnode(&netlist,breaksfd); printf("断开连接\n"); } void sigint(int signo){ if(userlist!=NULL){ int iuser=countsinglylist(userlist); while(iuser-->0){ userlist=userlist->next; usermesg *userupdate = (usermesg *)(userlist->content); userupdate->o_loghowtime=time(NULL)-userupdate->o_logintime; userupdate->o_rank+=userupdate->o_loghowtime/60; userupdate->o_status=0; memcpy(usermm+iuser,userlist->content,sizeof(usermesg)); } } exit(0); } void * initmmap(char *file,int size){ int fd=open(file,O_CREAT|O_RDWR,S_IRWXU|S_IRWXO|S_IRWXG); ftruncate(fd,size); void * mm = mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); printf("memory map:%x\n",mm); close(fd); return mm; } main(){ printf("%d\n",sizeof(usermesg)); signal(SIGPIPE,sigpipe); signal(SIGINT,sigint); int sfd = inittcpsocket(1209); usermm=(usermesg *)initmmap("usermesg.db",sizeof(usermesg)*mmp_usermesg_len); friendmm=(friendmesg *)initmmap("friendmesg.db",sizeof(friendmesg)* mmp_friendadd_len); srand(time(NULL)); int imm=0; while(1){ if((usermm+imm)->mesgtype==0) break; usermesg *useri=(usermesg *)malloc(sizeof(usermesg)); memcpy(useri,(usermm+imm),sizeof(usermesg)); if(userlist==NULL) userlist=initsinglylist((-imm)-1,useri); else addlistnode(userlist,(-imm)-1,useri); if(++imm==mmp_usermesg_len) break; } while(1){ struct sockaddr_in tempip; int sockaddrlen=sizeof(struct sockaddr_in); int csfd=accept(sfd,(struct sockaddr *)&tempip,&sockaddrlen); //无论是否建立连接,立刻返回 if(csfd != -1){ int sendbuff=1024*1024; setsockopt(csfd,SOL_SOCKET,SO_SNDBUF,&sendbuff,sizeof(sendbuff)); //缓冲区大小为1MB int recvbuff=1024*1024; setsockopt(csfd,SOL_SOCKET,SO_RCVBUF,&recvbuff,sizeof(recvbuff)); //缓冲区大小为1MB send(csfd,&csfd,sizeof(csfd),MSG_DONTWAIT); //发送客户端唯一编号 printf("%d\n",csfd); deletelistnode(&netlist,csfd); netinfo *info=(netinfo *)malloc(sizeof(netinfo)); memcpy(&info->address,&tempip,sockaddrlen); info->port=ntohs(tempip.sin_port); inet_ntop(AF_INET,&tempip.sin_addr.s_addr,info->ip,sizeof(info->ip)); if(netlist!=NULL) addlistnode(netlist,csfd,info); else netlist=initsinglylist(csfd,info); printf("count:%d,ip:%s,port:%d\n",countsinglylist(netlist),info->ip,info->port); } if(csfd==-1){ int icsfd=countsinglylist(netlist); for(;icsfd>0;icsfd--){ int cfd=netlist->id; breaksfd=cfd; unitmesg mesg; int n = recv(cfd,&mesg,sizeof(mesg),MSG_DONTWAIT); if(n==0) kill(getpid(),SIGPIPE); //直到捕捉函数执行完毕后返回 if(n==sizeof(unitmesg)){ if(mesg.mesgtype==11){ //匿名登陆 char named[16]={'\0'}; strcpy(named,mesg.message); int j= countsinglylist(guestlist); for(;j>0;j--){ guestinfo *guest = (guestinfo *)(guestlist->content); //printf("strcmp %d\n",strcmp(guest->name,named)); if(strcmp(guest->name,named)==0){ mesg.message[0]='\0'; mesg.msglen=0; send(cfd,&mesg,sizeof(mesg),MSG_DONTWAIT); //发送匿名注册失败 break; } guestlist=guestlist->next; } if(j==0){ guestinfo *guest = (guestinfo *)malloc(sizeof(guestinfo)); guest->namlen=mesg.msglen; strcpy(guest->name,mesg.message); if(guestlist==NULL) guestlist = initsinglylist(cfd,guest); else addlistnode(guestlist,cfd,guest); send(cfd,&mesg,sizeof(mesg),MSG_DONTWAIT); //发送匿名注册成功 printf("客户端请求:%d,客户端匿名:%s\n",mesg.mesgtype,mesg.message); } } if(mesg.mesgtype==110){ //匿名注销 deletelistnode(&guestlist,cfd); } if(mesg.mesgtype==111){ //查看所有匿名用户 int ii=countsinglylist(guestlist); int total=sizeof(mesg.message)/sizeof(guestinfo); int size=0; mesg.msglen=0; while(1){ if(ii==0){ mesg.mesgtype=999; send(cfd,&mesg,sizeof(mesg),MSG_DONTWAIT); break; } if(size==total){ send(cfd,&mesg,sizeof(mesg),MSG_DONTWAIT); mesg.msglen=0; size=0; } guestlist=guestlist->next; guestinfo *guest = (guestinfo *)(guestlist->content); mesg.msglen+=sizeof(guestinfo); memcpy(mesg.message+size*sizeof(guestinfo),guest,sizeof(guestinfo)); size++; ii--; } //printf("发送昵称剩下%d\n",ii); } if(mesg.mesgtype==1111){ //发送匿名世界聊天信息 if(grouplist!=NULL && searchlistnode(grouplist,1)!=NULL){ singlylist **guestchathead= (singlylist **)(searchlistnode(grouplist,1)->content); if(guestchathead!=NULL){ int iguest = countsinglylist(*guestchathead); //printf("多少个聊天信息%d\n",iguest); while(1){ if(iguest-->0){ *guestchathead=(*guestchathead)->next; guestmesg *guestchat=(guestmesg *)((*guestchathead)->content); printf("名字%s,内容%s\n",guestchat->name,guestchat->message); if(guestchat!=NULL){ guestmesg guestmessage; //memset(&guestmessage,0,sizeof(guestmesg)); guestmessage.mesgtype=1111; guestmessage.meslen=guestchat->meslen; memcpy(guestmessage.message,guestchat->message,guestchat->meslen); guestmessage.namlen=guestchat->namlen; strcpy(guestmessage.name,guestchat->name); send(cfd,&guestmessage,sizeof(guestmesg),MSG_DONTWAIT); //发送给客户端 } }else{ break; } } } } guestmesg mesgend; mesgend.mesgtype=1111; mesgend.namlen=0; mesgend.name[0]='\0'; mesgend.meslen=0; mesgend.message[0]='\0'; send(cfd,&mesgend,sizeof(mesgend),MSG_DONTWAIT); //发送结束信息 } if(mesg.mesgtype==1112){ //接收匿名聊天信息 guestmesg *guestm=(guestmesg *)&mesg; if(grouplist==NULL){ singlylist **guestchathead=(singlylist **)malloc(sizeof(singlylist **)); grouplist=initsinglylist(1,guestchathead); guestmesg *content =(guestmesg *)malloc(sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); memcpy(content,guestm,sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); *guestchathead=initsinglylist(1,content); }else{ if(searchlistnode(grouplist,1)==NULL){ singlylist **guestchathead=(singlylist **)malloc(sizeof(singlylist **)); addlistnode(grouplist,1,guestchathead); guestmesg *content =(guestmesg *)malloc(sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); memcpy(content,guestm,sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); *guestchathead=initsinglylist(1,content); }else{ singlylist **guestchathead=(singlylist **)(searchlistnode(grouplist,1)->content); int iguest = countsinglylist(*guestchathead); if(iguest==group_message_len){ deletelistnode(guestchathead,1); int ioguest=1; while(1){ searchlistnode(*guestchathead,ioguest+1)->id=ioguest; ioguest++; if(ioguest==group_message_len) break; } }else iguest++; guestmesg *content =(guestmesg *)malloc(sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); memcpy(content,guestm,sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); addlistnode(*guestchathead,iguest,content); } } printf("[%s]:%s\n",guestm->name,guestm->message); } if(mesg.mesgtype==21){ //注册用户 usermesg *ureg = (usermesg *)&mesg; if(ureg->s_lognamlen==0||ureg->s_logpaslen==0||ureg->s_phone==0){ ureg->mesgtype=0; send(cfd,ureg,sizeof(usermesg),MSG_DONTWAIT); //注册失败,注册信息不规范 } if(ureg->s_phone>0 && ureg->s_lognamlen>0 && ureg->s_logpaslen>0){ int iregname=countsinglylist(userlist); while(1){ if(--iregname<0) break; usermesg *usercmp = (usermesg *)(userlist->content); //printf("注册:[%s]\n",ureg->s_logname); if(strcmp(ureg->s_logname,usercmp->s_logname)==0) break; userlist=userlist->next; } if(iregname<0){ while(1){ ureg->o_userid=(unsigned int)rand(); int iid=countsinglylist(userlist); while(1){ if(--iid<0) break; if(ureg->o_userid==((usermesg *)(userlist->content))->o_userid) break; userlist=userlist->next; } if(iid<0) break; } int imm=countsinglylist(userlist); if(imm==mmp_usermesg_len){ printf("用户数量已经溢出!\n"); ureg->mesgtype=0; ureg->o_userid=1; send(cfd,ureg,sizeof(usermesg),MSG_DONTWAIT); //注册失败,用户数量已经溢出 } if(immm_netnamlen=ureg->s_lognamlen; strcpy(ureg->m_netname,ureg->s_logname); ureg->s_regitime=time(NULL); strcpy( ureg->s_regiip ,((netinfo *)(netlist->content))->ip); ureg->o_rank=0; ureg->p_sex=0; usermesg *user=malloc(sizeof(usermesg)); memcpy(user,ureg,sizeof(usermesg)); if(userlist!=NULL) addlistnode(userlist,-cfd,user); else userlist = initsinglylist(-cfd,user); send(cfd,ureg,sizeof(usermesg),MSG_DONTWAIT); //注册成功 printf("新用户[%s]注册\n",ureg->s_logname); } } if(iregname>=0){ ureg->mesgtype=0; ureg->s_lognamlen=0; send(cfd,ureg,sizeof(usermesg),MSG_DONTWAIT); //注册失败,用户名重复 } } } if(mesg.mesgtype==12){ //用户登录 usermesg *umesg = (usermesg *)&mesg; int ilogin=countsinglylist(userlist); if(ilogin==0){ umesg->mesgtype=0; umesg->s_lognamlen=0; send(cfd,umesg,sizeof(usermesg),MSG_DONTWAIT); //登录失败,用户不存在 } mesg.mesgtype=0; while(1){ if(--ilogin<0) break; usermesg *userll=((usermesg *)(userlist->content)); if(userll->s_lognamlen==umesg->s_lognamlen){ if(strcmp(userll->s_logname,umesg->s_logname)==0){ if(strcmp(userll->s_logpassword,umesg->s_logpassword)==0){ if(userll->o_status==0){ //未登录 memcpy(umesg,userll,sizeof(usermesg)); userll->o_status=1; userll->o_logintime=time(NULL); strcpy(userll->o_lateloginip,((netinfo *)(netlist->content))->ip); userlist->id=cfd; umesg->mesgtype=12; send(cfd,umesg,sizeof(usermesg),MSG_DONTWAIT); //登录成功 printf("登录成功:%s\n",umesg->s_logname); break; } if(cfd!=userlist->id){ //另一个客户端重复登录 memcpy(umesg,userll,sizeof(usermesg)); if(strcmp(userll->o_lateloginip,((netinfo *)(netlist->content))->ip)!=0) printf("先后登录地址:%s,%s\n",userll->o_lateloginip,((netinfo *)(netlist->content))->ip); strcpy(userll->o_lateloginip,((netinfo *)(netlist->content))->ip); close(userlist->id); //shutdown(userlist->id,SHUT_RDWR); deletelistnode(&netlist,userlist->id); userlist->id=cfd; umesg->mesgtype=12; send(cfd,umesg,sizeof(usermesg),MSG_DONTWAIT); //登录成功 break; } } else{ umesg->s_logpaslen=0; break; } } } userlist=userlist->next; } if(umesg->mesgtype==0){ if(ilogin<0) umesg->s_lognamlen=0; send(cfd,umesg,sizeof(usermesg),MSG_DONTWAIT); //登录失败,密码不匹配 } } if(mesg.mesgtype==120){ //用户退出登录 singlylist *closeusernode=searchlistnode(userlist,cfd); if(closeusernode!=NULL){ closeusernode->id=-cfd; usermesg *userupdate = (usermesg *)(closeusernode->content); userupdate->o_loghowtime=time(NULL)-userupdate->o_logintime; userupdate->o_rank+=userupdate->o_loghowtime/60; userupdate->o_status=0; } } if(mesg.mesgtype==12351){ //发送实名世界聊天信息 usermesg *userworld = (usermesg *)(searchlistnode(userlist,cfd)->content); userworld->o_status|=0x10; if(grouplist!=NULL && searchlistnode(grouplist,2)!=NULL){ singlylist **guestchathead= (singlylist **)(searchlistnode(grouplist,2)->content); if(guestchathead!=NULL){ int iguest = countsinglylist(*guestchathead); //printf("多少个聊天信息%d\n",iguest); while(1){ if(iguest-->0){ *guestchathead=(*guestchathead)->next; guestmesg *guestchat=(guestmesg *)((*guestchathead)->content); printf("名字%s,内容%s\n",guestchat->name,guestchat->message); if(guestchat!=NULL){ guestmesg guestmessage; //memset(&guestmessage,0,sizeof(guestmesg)); guestmessage.mesgtype=1111; guestmessage.meslen=guestchat->meslen; memcpy(guestmessage.message,guestchat->message,guestchat->meslen); guestmessage.namlen=guestchat->namlen; strcpy(guestmessage.name,guestchat->name); send(cfd,&guestmessage,sizeof(guestmesg),MSG_DONTWAIT); //发送给客户端 } }else{ break; } } } } guestmesg mesgend; mesgend.mesgtype=12351; mesgend.namlen=0; mesgend.name[0]='\0'; mesgend.meslen=0; mesgend.message[0]='\0'; send(cfd,&mesgend,sizeof(mesgend),MSG_DONTWAIT); //发送结束信息 } if(mesg.mesgtype==12352){ //接收实名聊天信息 guestmesg *guestm=(guestmesg *)&mesg; if(grouplist==NULL){ singlylist **guestchathead=(singlylist **)malloc(sizeof(singlylist **)); grouplist=initsinglylist(2,guestchathead); guestmesg *content =(guestmesg *)malloc(sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); memcpy(content,guestm,sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); *guestchathead=initsinglylist(1,content); }else{ if(searchlistnode(grouplist,2)==NULL){ singlylist **guestchathead=(singlylist **)malloc(sizeof(singlylist **)); addlistnode(grouplist,2,guestchathead); guestmesg *content =(guestmesg *)malloc(sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); memcpy(content,guestm,sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); *guestchathead=initsinglylist(1,content); }else{ singlylist **guestchathead=(singlylist **)(searchlistnode(grouplist,2)->content); int iguest = countsinglylist(*guestchathead); if(iguest==group_message_len){ deletelistnode(guestchathead,1); int ioguest=1; while(1){ searchlistnode(*guestchathead,ioguest+1)->id=ioguest; ioguest++; if(ioguest==group_message_len) break; } }else iguest++; guestmesg *content =(guestmesg *)malloc(sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); memcpy(content,guestm,sizeof(guestmesg)-(sizeof(guestm->message)-guestm->meslen)); addlistnode(*guestchathead,iguest,content); } } printf("[%s]:%s\n",guestm->name,guestm->message); } if(mesg.mesgtype==12353){ //请求实名世界陌生人 int ii=countsinglylist(userlist); int total=sizeof(mesg.message)/sizeof(guestinfo); int size=0; mesg.msglen=0; while(1){ if(ii==0){ mesg.mesgtype=999; send(cfd,&mesg,sizeof(mesg),MSG_DONTWAIT); break; } if(size==total){ send(cfd,&mesg,sizeof(mesg),MSG_DONTWAIT); mesg.msglen=0; size=0; } userlist=userlist->next; int status=((usermesg *)(userlist->content))->o_status; if( (status & 0x10)>>4==1 ){ guestinfo guest; strcpy(guest.name,((usermesg *)(userlist->content))->m_netname); guest.namlen=((usermesg *)(userlist->content))->m_netnamlen; mesg.msglen+=sizeof(guestinfo); memcpy(mesg.message+size*sizeof(guestinfo),&guest,sizeof(guestinfo)); size++; } ii--; } } if(mesg.mesgtype==12350){ //请求退出实名世界聊天 usermesg *userworld = (usermesg *)(searchlistnode(userlist,cfd)->content); userworld->o_status &=~0x10; } if(mesg.mesgtype==12111){ //通过匿名交友 char name[16]; strcpy(name,mesg.message); int size=countsinglylist(userlist); userlist=userlist->next; while(1){ usermesg *userm=(usermesg *)userlist->content; //printf("%d\n",sizeof(usermesg)); if(strcmp(userm->m_netname,name)==0){ userm->mesgtype=12111; send(cfd,userm,sizeof(usermesg),MSG_DONTWAIT); } userlist=userlist->next; if(--size==0){ userm->mesgtype=999; send(cfd,userm,sizeof(usermesg),MSG_DONTWAIT); char *logname=((usermesg *)searchlistnode(userlist,cfd)->content)->s_logname; printf("[%s]添加[%s]\n",logname,name); break; } } } } if(n==-1){ //客户端没有请求 } if(netlist!=NULL) netlist=netlist->next; } } } } //fcntl(csfd, F_SETFL, fcntl(sfd, F_GETFL, 0) | O_NONBLOCK);