5.26作业

服务器

cs 复制代码
  2 
  3 #define BUFSIZE 1024
  4 #define login_msg_len 20
  5 
  6 typedef struct Node{
  7     char name[login_msg_len];
  8     struct sockaddr_in addr;
  9     struct Node *next;
 10 }Node;
 11 
 12 typedef struct Msgtype{
 13     char type;
 14     char username[login_msg_len];
 15     char content[BUFSIZE];
 16 }Msgtype;
 17 
 18 Node *create_node(in_port_t SER_PORT,const char * SER_IP_STR);
 19 Node *add_node(char *name,struct sockaddr_in addr);
 20 int print_msg(Msgtype *msg);
 21 void broadcast(int sfd,Node *head,Msgtype *msg);
 22 int is_exist(Node *head,Msgtype *msg);
 23 int is_empty(Node *head);
 24 void insert_node(Node *head,char *name,struct sockaddr_in addr);
 25 void delete_node(Node *head,char *name);
 26 void broadcast_system(int sfd,Node *head,char *input_buf);
 27 
 28 int main(int argc, char const *argv[])
 29 {
 30     if(3>argc){
 31         printf("输入格式不对,请按照以下格式输入:./server ip port\n");
 32         exit(1);
 33     }
 34     const char *SER_IP_STR=argv[1];
 35     in_port_t SER_PORT=atoi(argv[2]);
 36 
 37     int sfd=-1;
 38     if((sfd=socket(AF_INET,SOCK_DGRAM,0))<0){
 39         perror("socket");
 40         exit(1);
 41     }
 42 
 43     struct sockaddr_in addr;
 44     memset(&addr,0,sizeof(addr));
 45     addr.sin_family=AF_INET;
 46     addr.sin_port=htons(SER_PORT);
 47     if(inet_aton(SER_IP_STR,&addr.sin_addr)==0){
 48         perror("inet_aton");
 49         exit(1);
 50     }
 51 
 52     if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr))<0){
 53         perror("bind");
 54         exit(1);
 55     }
 56     printf("bind success\n");
 57     Node *head=create_node(SER_PORT,SER_IP_STR);
 58 
 59     struct pollfd pfd[2];
 60     pfd[0].fd = sfd;
 61     pfd[0].events = POLLIN;
 62     pfd[1].fd = 0;
 63     pfd[1].events = POLLIN;
 64 
 65     struct sockaddr_in client_addr;
 66     socklen_t client_addr_len=sizeof(client_addr);
 67 
 68     Msgtype client_msg;
 69     memset(&client_msg,0,sizeof(client_msg));
 70 
 71     while(1){
 72         int ret=poll(pfd,2,-1);
 73         if(ret<0){
 74             perror("poll");
 75             exit(1);
 76         }else if (ret==0){
 77             printf("poll timeout\n");
 78             continue;
 79         }
 80         if(pfd[0].revents==POLLIN){
 81             int recv_len=recvfrom(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,&client_addr_l
 82             if(recv_len<0){
 83                 perror("recvfrom");
 84                 exit(1);
 85             }
 86             if(print_msg(&client_msg)==1){
 87                 if(is_exist(head,&client_msg)){
 88                     client_msg.type='E';
 89                     sendto(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,sizeof(client_addr));
 90                     continue;
 91                 }else{
 92                     insert_node(head,client_msg.username,client_addr);
 93                     client_msg.type='L';
 94                    strcpy(client_msg.content,"进入聊天室");
 95                     broadcast(sfd,head,&client_msg);
 96                 }
 97             }else if (print_msg(&client_msg)==2){
 98                 printf("%s发送消息\n",client_msg.username);
 99                 broadcast(sfd,head,&client_msg);
100             }else if (print_msg(&client_msg)==3){
101                 delete_node(head,client_msg.username);
102                 client_msg.type='Q';
103                 strcpy(client_msg.content,"退出聊天室");
104                 broadcast(sfd,head,&client_msg);
105             }else{
106                 char *msg="消息类型错误";
107                 for(int i=0;i<sizeof(msg);i++){
108                     client_msg.content[i]=msg[i];
109                 }
110                 sendto(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,sizeof(client_msg));
111                 continue;
112             }
113         }
114         if(pfd[1].revents==POLLIN){
115             char input_buf[BUFSIZE];
116             fgets(input_buf,BUFSIZE,stdin);
117             input_buf[strlen(input_buf)-1]='\0';
118             if(is_empty(head)){
119                 printf("聊天室为空,请等待其他用户登录\n");
120                 continue;
121             }
122             broadcast_system(sfd,head,input_buf);
123         }
124     }
125     close(sfd);
126     return 0;
127 }
128 Node *create_node(in_port_t SER_PORT,const char * SER_IP_STR){
129     Node *node=(Node*)malloc(sizeof(Node));
130     if(node==NULL){
131         perror("malloc");
132         exit(1);
133     }
134     char *msg="system";
135     for(int i=0;i<sizeof(msg);i++){
136         node->name[i]=msg[i];
137     }
138     node->addr.sin_family=AF_INET;
139     node->addr.sin_port=htons(SER_PORT);
140     node->addr.sin_addr.s_addr=inet_addr(SER_IP_STR);
141     node->next=NULL;
142     return node;
143 }
144 Node *add_node(char *name,struct sockaddr_in addr){
145     Node *new_node=(Node*)malloc(sizeof(Node));
146     if(new_node==NULL){
147         perror("malloc");
148         exit(1);
149     }
150     strcpy(new_node->name,name);
151     new_node->addr=addr;
152     new_node->next=NULL;
153     return new_node;
154 }
155 int is_empty(Node *head){
156     if(head==NULL){
157         return 1;
158     }
159     return head->next==NULL?1:0;
160 }
161 void insert_node(Node *head,char *name,struct sockaddr_in addr){
162     if(head==NULL){
163         perror("head is null");
164         exit(1);
165     }
166     Node *new_node=add_node(name,addr);
167     new_node->next=head->next;
168     head->next=new_node;
169     printf("%s进入聊天室\n",name);
170 }
171 int print_msg(Msgtype *msg){
172     switch(msg->type){
173         case 'L':
174             return 1;
175         case 'C':
176             return 2;
177         case 'Q':
178             return 3;
179         default:
180             return 0;
181     }
182 }
183 int is_exist(Node *head,Msgtype *msg){
184     if(head==NULL){
185         perror("head is null");
186         exit(1);
187     }
188     if(is_empty(head)){
189         return 0;
190     }
191     Node *p=head->next;
192     while(p!=NULL){
193         if(strcmp(p->name,msg->username)==0){
194             return 1;
195         }
196         p=p->next;
197     }
198     return 0;
199 }
200 void broadcast(int sfd,Node *head,Msgtype *msg){
201     if(head==NULL){
202         perror("head is null");
203         exit(1);
204     }
205     if(is_empty(head)){
206         printf("聊天室为空\n");
207         return;
208     }
209     Node *p=head->next;
210     while(p!=NULL){
211         if(strcmp(p->name,msg->username)!=0){
212             sendto(sfd,msg,sizeof(Msgtype),0,(struct sockaddr*)&p->addr,sizeof(p->addr));
213         }
214         p=p->next;
215 
216     }
217 }
218 void delete_node(Node *head,char *name){
219     if(head==NULL){
220         perror("head is null");
221         exit(1);
222     }
223     if(is_empty(head)){
224         printf("聊天室为空\n");
225         return;
226     }
227     printf("%s退出聊天室\n",name);
228     Node *p=head->next;
229     Node *pre=head;
230     while(p!=NULL){
231         if(strcmp(p->name,name)==0){
232             pre->next=p->next;
233             free(p);
234             return;
235         }
236         pre=p;
237         p=p->next;
238     }
239 
240 }
241 void broadcast_system(int sfd,Node *head,char *content){
242     if(head==NULL){
243         perror("head is null");
244         exit(1);
245     }
246     if(is_empty(head)){
247         printf("聊天室为空\n");
248         return;
249     }
250     Msgtype msg;
251     msg.type='C';
252     strcpy(msg.username,"system");
253     strcpy(msg.content,content);
254     Node *p=head->next;
255     while(p!=NULL){
256         sendto(sfd,&msg,sizeof(Msgtype),0,(struct sockaddr*)&p->addr,sizeof(p->addr));
257         p=p->next;
258     }
259     printf("system发送消息:%s\n",content);
260 }
~                                                                                                                       
~                                                                                                                       

客户端

cs 复制代码
 #include <header.h>
 #define BUFSIZE 1024
 #define login_msg_len 20 

 
 typedef struct Msgtype{
     char type;
     char username[login_msg_len];
     char content[BUFSIZE];
 }Msgtype;
 
 int main(int argc, char const *argv[])
 {
     
     if(3>argc){                                                                                                                                            
         printf("输入格式不对,请按照以下格式输入:./server ip port\n");
     }
     const char *SER_IP_STR=argv[1];
     int SER_PORT=atoi(argv[2]);
 
    
     int sfd=-1;
     if((sfd=socket(AF_INET,SOCK_DGRAM,0))<0){
         perror("socket");
         exit(1);
     }
 
    
     struct sockaddr_in server_addr;
     memset(&server_addr,0,sizeof(server_addr));
     server_addr.sin_family=AF_INET;
     server_addr.sin_port=htons(SER_PORT);
     if(inet_aton(SER_IP_STR,&server_addr.sin_addr)==0){
         perror("inet_aton");
         exit(1);
     }
     socklen_t addr_len=sizeof(server_addr);
 
    
     Msgtype recv_msg;
     memset(&recv_msg,0,sizeof(recv_msg));
     Msgtype send_msg;
     memset(&send_msg,0,sizeof(send_msg));
 
     
     Msgtype login_msg;
 
     while (1)
     {
         
 
         memset(&login_msg,0,sizeof(login_msg));
         login_msg.type='L';
         printf("请输入用户名:");
         fgets(login_msg.username, login_msg_len, stdin);
         login_msg.username[strcspn(login_msg.username, "\n")] = '\0'; 
 
       
         if (sendto(sfd, &login_msg, sizeof(login_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
         {
             perror("sendto");
             exit(1);
         }
 
         
         struct pollfd pfd[2];
         pfd[0].fd = sfd;        
         pfd[0].events = POLLIN; 
         pfd[1].fd = 0;         
         pfd[1].events = POLLIN; 
 
         while(1){
            
             int ret=poll(pfd,2,-1);
             if(ret<0){
                 perror("poll");
                 exit(1);
             }else if (ret==0)
             {
                 printf("poll timeout\n");
                 continue;
             }
 
             if(pfd[0].revents==POLLIN){
                
                 int len=recvfrom(sfd, &recv_msg, sizeof(recv_msg), 0, (struct sockaddr *)&server_addr, &addr_len);
                 if(len<0){
                     perror("recvfrom");
                     exit(1);
                 }
                 if(recv_msg.type=='L'){
                     printf("-----------%s加入聊天室----------\n",recv_msg.username);
                 }else if(recv_msg.type=='C'){
                     printf("%s:%s\n",recv_msg.username,recv_msg.content);
                 }else if (recv_msg.type=='Q') {
                     printf("------------%s%s---------------\n",recv_msg.username,recv_msg.content);
                 }else{
                     printf("%s用户名已存在或服务器故障,请重新登录\n",login_msg.username);
                     break;
                 }
             }
             if(pfd[1].revents==POLLIN){
                
                 char input[BUFSIZE];
                 fgets(input,BUFSIZE, stdin);
                 input[strcspn(input, "\n")] = '\0'; 
                 if(strcmp(input,"quit")==0){
                     send_msg.type='Q';
                     sendto(sfd, &send_msg, sizeof(send_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
                     break;//退出循环
                 }else{
                     memset(&send_msg,0,sizeof(send_msg));
                     send_msg.type='C';
                     strncpy(send_msg.username,login_msg.username,login_msg_len);
                     strncpy(send_msg.content,input,BUFSIZE);
                     sendto(sfd, &send_msg, sizeof(send_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
                 }
             }
         }
     }
     close(sfd);
     return 0;
 }
                                                                                                                                                            
                                                                                                                                                            
相关推荐
AI街潜水的八角40 分钟前
基于C++的决策树C4.5机器学习算法(不调包)
c++·算法·决策树·机器学习
白榆maple1 小时前
(蓝桥杯C/C++)——基础算法(下)
算法
JSU_曾是此间年少1 小时前
数据结构——线性表与链表
数据结构·c++·算法
sjsjs111 小时前
【数据结构-合法括号字符串】【hard】【拼多多面试题】力扣32. 最长有效括号
数据结构·leetcode
此生只爱蛋2 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
blammmp2 小时前
Java:数据结构-枚举
java·开发语言·数据结构
昂子的博客3 小时前
基础数据结构——队列(链表实现)
数据结构
咕咕吖3 小时前
对称二叉树(力扣101)
算法·leetcode·职场和发展
九圣残炎3 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
lulu_gh_yu3 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法