服务器
2 3 #define BUFSIZE 10244 #define login_msg_len 205 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_l82 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 }
~
~
客户端
#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;}