//服务器端 #include "Header.h" typedef struct { char name[10]; SA_IN address; }USER; //XXX :用户链表 typedef struct Hnode_list { USER data; struct Hnode_list *next; }Hlink,*plink; int memoryError(plink p) ; int creatUserList(plink head); int findUser(plink head,char name[10]); int delUser(plink head,char name[10]); int getAllUser(plink const head); int addUser(plink head,USER data); //XXX :用户链表 void ProcessLogin(char* command,SA_IN rec_addr); void ProcessChat(char* command); plink head; int main(void) { char buf[BUFFERSIZE]; SA_IN address, rec_addr; int socket_fd; socklen_t length; head=malloc(sizeof(Hlink));//用户列表头 creatUserList(head); //创建列表 if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) == -1) { perror("套接字创建失败"); exit(-1); } memset(&address,0,sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr("127.0.0.1"); address.sin_port = htons(8000); if(bind(socket_fd,(SA *)&address,sizeof(address)) == -1) { perror("套接字绑定失败"); exit(-1); } int i=0; length = sizeof(rec_addr); while(1) { printf("==%d==\n",i); if(recvfrom(socket_fd,buf,sizeof(buf),0,(SA *)&rec_addr,&length) == -1) { perror("接收消息失败"); } printf("%hu\n",ntohs(rec_addr.sin_port)); switch(buf[0]) { case 'L': ProcessLogin(buf,rec_addr); break; case 'C': ProcessChat(buf); break; case 'Q':break; default : printf("ERROR");break; } i++; } close(socket_fd); } void ProcessLogin(char* command,SA_IN rec_addr) { int socket_fd; char name[10]; char ip[32]; char buf[BUFFERSIZE]; USER user; strcpy(name,command+1); strcpy(ip,inet_ntoa(rec_addr.sin_addr)); if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) == -1) { perror("套接字创建失败"); exit(-1); } if(findUser(head,name)==-1) { strcpy(user.name,name); user.address=rec_addr; addUser(head,user); buf[0]='Y'; if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&rec_addr,sizeof(rec_addr))==-1) { perror("登录失败"); } } else { buf[0]='N'; if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&rec_addr,sizeof(rec_addr))==-1) { perror("登录失败"); } } close(socket_fd); } void ProcessChat(char* command) { int socket_fd; char buf[BUFFERSIZE]; SA_IN address; if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) == -1) { perror("套接字创建失败"); exit(-1); } plink p=head->next; while(p!=NULL) { address=(p->data).address; sprintf(buf,"%s\n",command+1); // if(strncmp(buf,(p->data).name,strlen((p->data).name))==0) //屏蔽属于自己的消息 // continue; if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&address,sizeof(address))<0) { perror("消息发送失败"); } printf("%s:%hu\n",buf,ntohs(address.sin_port)); p=p->next; } close(socket_fd); } //XXX:使用带头结点的单向链表 存放用户信息 int memoryError(plink p) //判断内存是否申请成功 { if(p==NULL) { printf("MEMORY ERROR!"); return 1; } return 0; } int creatUserList(plink head) { if(memoryError(head)) return -1; head->next=NULL; } int addUser(plink head,USER data) //始终在表头插入 { plink new_create=malloc(sizeof(Hlink)); if(memoryError(new_create)) return -1; new_create->data=data; new_create->next=head->next; head->next=new_create; } int getAllUser(plink const head) { plink p=head->next; while(p!=NULL) { printf("%s:%s:%hu\n",(p->data).name,inet_ntoa((p->data).address.sin_addr) ,ntohs((p->data).address.sin_port)); p=p->next; } } int delUser(plink head,char name[10]) { plink q=head; plink p=head->next; while(p!=NULL) { if(strcmp((p->data).name,name)==0) break; q=p; p=p->next; } if(p==NULL) { printf("删除用户失败\n"); return -1; } q->next=p->next; free(p); p=NULL; } int findUser(plink head,char name[10]) { plink p=head->next; while(p!=NULL) { if(strcmp((p->data).name,name)==0) return 0; p=p->next; } if(p==NULL) return -1; } //XXX:使用带头结点的单向链表 存放用户信息
//客户端#include "Header.h" void dispMessage(int signo); void killAll(int signo); char* ProcessLogin(SA_IN serv_addr); pid_t pid; int main(void) { signal(SIGUSR1,dispMessage); signal(SIGINT,killAll); int socket_fd; char buf[BUFFERSIZE]; char name[10]; SA_IN serv_addr; //XXX:服务器配置信息 memset(&serv_addr,0,sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(8000); //XXX strcpy(name,ProcessLogin(serv_addr)); if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) == -1) { perror("套接字创建失败"); exit(-1); } if((pid=fork())==-1) { perror("子进程创建失败"); return -1; } if(pid==0)//子进程 { sprintf(buf,"C%s上线了",name); //sendto在此处相当于第一次放送,这跟tcp connect 差不多,会自动分配ip端口号、、错误根源 if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&serv_addr,sizeof(serv_addr)) < 0) { perror("发送失败"); } while(1) { pause(); if(recvfrom(socket_fd,buf,sizeof(buf),0,NULL,NULL)==-1) { perror("接收消息失败"); } printf("[收到消息]%s\n",buf); } } char buf_temp[BUFFERSIZE]; while(1)//父进程 { printf("<请输入>"); scanf("%s", buf_temp); sprintf(buf,"C%s说:%s",name,buf_temp); if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&serv_addr,sizeof(serv_addr)) < 0) { perror("发送失败"); } kill(pid,SIGUSR1); } } //Siganl// void killAll(int signo) { printf("\n%d进程结束\n",getpid()); exit(-1); } void dispMessage(int signo) { ; } //Siganl// char* ProcessLogin(SA_IN serv_addr) { int socket_fd; char buf[BUFFERSIZE]; static char name[10]; if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) == -1) { perror("套接字创建失败"); exit(-1); } while(1) { printf("请输入用户名:"); buf[0]='L'; scanf("%s",buf+1); strcpy(name,buf+1); if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&serv_addr,sizeof(serv_addr)) < 0) { perror("登录失败"); } recvfrom(socket_fd,buf,sizeof(buf),0,NULL,NULL); if(buf[0]=='N') { printf("该用户名已被使用,请重新输入用户名\n"); } else if(buf[0]=='Y') { printf("登录成功\n"); close(socket_fd); return name; break; } } //printf("==END===\n"); } //错误原因
yang@ubuntu:~/Day_33/ChartRoom$ ./Server ==0== 43490//登陆端口号 ==1== 42934//子进程接受的端口号,不匹配 liu上线了 :43490 ==2== 42934 liu说:sdasda :43490 ==3== 42934 liu说:sadasda :43490 ==4== 42934 liu说:adasdas :4
UDP 聊天室实现 经典错误
最新推荐文章于 2024-05-24 18:50:55 发布