项目需求:
- 如果有用户登录,其他用户可以收到这个人的登录信息
- 如果有人发送信息,其他用户可以收到这个人的群聊信息
- 如果有人下线,其他用户可以收到这个人的下线信息
- 服务器可以发送系统信息
#include <myhead.h> typedef struct msgtyp { char type; char usrname[20]; char msgtext[1024]; }msg_t; typedef struct datatype { char name[20]; struct sockaddr_in cin; }data_t; typedef struct node { union { struct node *tail; data_t data; }; struct node* next; }node,*node_p; node_p create_head() { node_p H=(node_p)malloc(sizeof(node)); if(H==NULL) { printf("空间申请失败\n"); return NULL; } H->next = NULL; H->tail = H; return H; } int insert_tail(node_p H,data_t data) { if(H==NULL) { printf("入参为空\n"); return -1; } node_p new=(node_p)malloc(sizeof(node)); if(new==NULL) { printf("空间申请失败\n"); return -1; } new->data = data; H->tail->next = new; H->tail = new; return 1; } int main(int argc, const char *argv[]) { unsigned short SER_PORT; char SER_IP[20]=""; printf("服务器ip:"); scanf("%s",SER_IP); printf("服务器端口号:"); scanf("%hd",&SER_PORT); int sfd = socket(AF_INET,SOCK_DGRAM,0); if(sfd == -1) { perror("socket error"); return -1; } struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(SER_PORT); sin.sin_addr.s_addr = inet_addr(SER_IP); if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1) { perror("bind error"); return -1; } fd_set readfds,tempfds; FD_ZERO(&readfds); FD_SET(0,&readfds); FD_SET(sfd,&readfds); int maxfd = sfd; struct sockaddr_in cin_arr[1024]; struct sockaddr_in cin; socklen_t c_socklen=sizeof(cin); node_p H=create_head(); data_t data; msg_t msgbuf; // bzero(data,sizeof(data)); while(1) { tempfds = readfds; int res = select(maxfd+1,&tempfds,NULL,NULL,NULL); if(res == 0) { printf("time out \n"); return -1; } else if(res == -1) { perror("select error"); return -1; } for(int i=0; i<=maxfd;i++) { if(!FD_ISSET(i,&tempfds)) continue; if( i == sfd ) { recvfrom(sfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&cin,&c_socklen); // struct sockaddr_in cin_send =cin ; // socklen_t cin_send =sizeof(cin_send); char send_name[20]; strcpy(send_name,msgbuf.usrname); if( msgbuf.type == 'L' ) //登录 { data_t data; strcpy(data.name,msgbuf.usrname); data.cin = cin; insert_tail(H,data); //需要判断一下注册的名字是否存在 strcat(msgbuf.msgtext,"success"); sendto(sfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&cin,sizeof(cin)); } if( msgbuf.type == 'C' ) { //data_t data; node_p p=H->next; while(p!=NULL) { if(strcmp(send_name,p->data.name)==0) { p=p->next; } else { cin = p->data.cin; sendto(sfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&cin,sizeof(cin)); p=p->next; } } printf("send success\n"); } } else if(i == 0) { msgbuf.type='C'; strcpy(msgbuf.usrname,"service"); fgets(msgbuf.msgtext, sizeof(msgbuf.msgtext), stdin); msgbuf.msgtext[strlen(msgbuf.msgtext)-1] = 0; node_p p=H->next; while(p!=NULL) { cin = p->data.cin; sendto(sfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&cin,sizeof(cin)); p=p->next; } printf("send success\n"); } } } return 0; }
#include <myhead.h> typedef struct msgtyp { char type; char usrname[20]; char msgtext[1024]; }msg_t; int main(int argc, const char *argv[]) { unsigned short CLI_PORT; unsigned short SER_PORT; char SER_IP[20]=""; char CLI_IP[20]=""; printf("服务器ip:"); scanf("%s",SER_IP); printf("服务器端口号:"); scanf("%hd",&SER_PORT); printf("客户端ip:"); scanf("%s",CLI_IP); printf("客户端口号:"); scanf("%hd",&CLI_PORT); int cfd = socket(AF_INET,SOCK_DGRAM,0); if(cfd == -1) { perror("socket error"); return -1; } // printf("sock\n"); struct sockaddr_in cin; cin.sin_family = AF_INET; cin.sin_port = htons(CLI_PORT); cin.sin_addr.s_addr = inet_addr(CLI_IP); if(bind(cfd,(struct sockaddr*)&cin,sizeof(cin))==-1) { perror("bind error"); return -1; } struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(SER_PORT); sin.sin_addr.s_addr = inet_addr(SER_IP); socklen_t s_socklen=sizeof(sin); char wbuf[128]=""; //数据包 msg_t msgbuf; printf("请注册名字:\n"); scanf("%s",msgbuf.usrname); char name[20]=""; strcpy(name,msgbuf.usrname); while(getchar()!=10); msgbuf.type = 'L'; sendto(cfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&sin,sizeof(sin)); // bzero(msgbuf,sizeof(msgbuf)); recvfrom(cfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&sin,&s_socklen); // printf("服务器的消息:%s\n",buf); if(strcmp(msgbuf.msgtext,"success")==0) { struct pollfd pfds[2]; pfds[0].fd = 0; pfds[0].events = POLLIN; pfds[1].fd = cfd; pfds[1].events = POLLIN; while(1) { int res = poll(pfds , 2, -1); if(res == 0) { printf("time out \n"); return -1; }else if(res == -1) { perror("poll error"); return -1; } //程序执行至此,说明集合中有事件产生,接下来根据不同的事件,执行不同的函数即可 if(pfds[0].revents == POLLIN) //判断是否为终端输入 { //从终端获取数据 fgets(wbuf, sizeof(wbuf), stdin); wbuf[strlen(wbuf)-1] = '\0'; if(strcmp(wbuf, "quit") == 0) { break; } msgbuf.type = 'C'; strcpy(msgbuf.usrname,name); strcpy(msgbuf.msgtext,wbuf); //讲数据发送给服务器 sendto(cfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&sin,sizeof(sin)); } //判断是否为服务器发来消息 if(pfds[1].revents == POLLIN) { //接收服务器发来的消息 recvfrom(cfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&sin,&s_socklen); if(msgbuf.type=='C') { printf("%s:%s\n",msgbuf.usrname,msgbuf.msgtext); } } } } return 0; }