📄 chatserver.c
字号:
//程序比较简单,就全放在一个文件里了//服务器维护一个用户列表,包括用户名和IP//响应用户加入和离开请求.//有新加入的用户或有用户离开,都要通知所有用户更新其用户列表#include <stdio.h>#include <time.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#include <arpa/inet.h>#include <string.h>#include <signal.h>#include <pthread.h>#define SERV_PORT 7000#define SUDP_PORT 7001//#define CLET_PORT 2029#define MESG_PORT 7002#define SEG_SIZE 5000#define err_sys printf#define MAXSIZE 1024#define NAMELEN 20#define LEN sizeof(user)typedef struct _user{ char name[NAMELEN]; char ip[16]; struct _user *next; struct _user *prev;}user;static user *head;user *tail;user *p;user *q;int lock;int usrnum;void add(char * name,char *ip){ int i; while(lock==1) i++; lock=1; if(head==NULL) { p=tail=head=(user *)malloc(LEN); head->prev=head->next=NULL; } else { p=(user *)malloc(LEN); tail->next=p; p->prev=tail; p->next=NULL; tail=p; } strcpy(p->name,name); strcpy(p->ip,ip); usrnum++;}void UserList(){ int i; while(lock==1) i++; lock=1; if(head==NULL) { printf("\nNo User now!\n\n"); return; } printf("The user list:\n\n"); printf("\tName"); printf("\t\t\t IP\n"); for(p=head;p!=NULL;p=p->next) { printf("\t%-15s",p->name); printf("%-20s\n",p->ip); } fflush(stdout); lock=0;}user *find(char *buf,int i){ p=head; while(p!=NULL) { if(strcmp((i==1)?p->ip:p->name,buf)==0) return p; p=p->next; } return NULL;}void del(char *buf){ int i; while(lock==1) i++; lock=1; user *result=find(buf,1); if(result==NULL) return; if(head==NULL) return; if(result==head) { head=result->next; if(head!=NULL) head->prev=NULL; else tail=NULL; } else if(result==tail) { tail=result->prev; tail->next=NULL; } else { result->prev->next=result->next; result->next->prev=result->prev; } free(result);}sendmessage(int type,char *ip,char *name){ int sockfd; int len; struct sockaddr_in servaddr; char buf[50]; memset(buf,0,50); if(type==0) { strcpy(buf,"+"); strcat(buf,name); strcat(buf,"\r"); strcat(buf,ip); strcat(buf,"\r\r"); } else { strcpy(buf,"-"); strcat(buf,ip); strcat(buf,"\r"); } for(p=head;p!=NULL;p=p->next) { bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(MESG_PORT); inet_aton(p->ip,&servaddr.sin_addr); sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(strcmp(ip,p->ip)==0) continue; len=sizeof(servaddr); sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&servaddr,len); } close(sockfd);}void sendall(int sock,struct sockaddr_in * pservaddr){ char buf[5000]; int len; memset(buf,0,5000); buf[0]='\0'; if(head!=NULL) for(p=head;p!=NULL;p=p->next) { strcat(buf,p->name); strcat(buf,"\r"); strcat(buf,p->ip); strcat(buf,"\r\r"); } len=sizeof(*pservaddr); sendto(sock,buf,sizeof(buf),0,(struct sockaddr *)pservaddr,len); }//监听用户的加入消息void* tcplisten(void){ struct sockaddr_in cliaddr, servaddr; socklen_t clilen; int listenfd; listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); listen(listenfd, 5); char name[NAMELEN]; char ip[16]; int connfd; int buflen; while(1) { memset(name,0,sizeof(name)); memset(ip,0,sizeof(ip)); clilen = sizeof(cliaddr); bzero(&cliaddr, sizeof(cliaddr)); connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); memset(name,0,NAMELEN); buflen=recv(connfd,name,NAMELEN,0); strcpy(ip,inet_ntoa(cliaddr.sin_addr)); if(strlen(name)==0) continue; printf("\nA new comer :\n\t%s\t%s\n",name,ip); fflush(stdout); add(name,ip); lock=0; sendall(connfd,&cliaddr); //所有用户信息发送到新加入的user sendmessage(0,ip,name); //通知所有用户,有new comer close(connfd); //tcp连接结束 }}//udp监听用户的离开消息void *udplisten(void){ int sock; struct sockaddr_in servaddr, cliaddr; sock = socket(AF_INET, SOCK_DGRAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SUDP_PORT); if(bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) { perror("bind error"); exit(1); } int len; char buf[1]; char ip[16]; while(1) { memset(buf,0,1); bzero(&cliaddr,sizeof(cliaddr)); len = sizeof(cliaddr); len=recvfrom(sock,buf,1, 0,(struct sockaddr *)&cliaddr,&len); if(buf[0]=='-') { strcpy(ip,inet_ntoa(cliaddr.sin_addr)); p=find(ip,1); fflush(stdout); if(p==NULL) printf("This user is not in the session,maybe in the last one!\n"); else printf("\n%s has Left!\t \tIP: %s\n",p->name,p->ip); fflush(stdout); del(ip); lock=0; sendmessage(1,ip,NULL); //通知所有用户有人离开 } }}//主程序响应用户输入int main(int argc, char **argv){ int ret; tail=head=NULL; usrnum=0; lock=0; pthread_t tcplisten_t; pthread_t udplisten_t; ret=pthread_create(&tcplisten_t,NULL,(void *)tcplisten,NULL); ret=pthread_create(&udplisten_t,NULL,(void *)udplisten,NULL); int choice; while(1) { printf("\nChat Server is running!"); printf("\nPlease input your choice:\n1.Show all user \n2.stop the server\n"); fflush(stdout); scanf("%d",&choice); getchar(); if(choice==1) { UserList(); } else { //先清理结构 pthread_cancel(tcplisten_t); pthread_cancel(udplisten_t); printf("the chat servert is stopped!\n\n"); exit(0); }//else }//while}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -