服务器端
#include <header.h>
typedef struct node
{char name[20];struct sockaddr_in cli_addr;struct node *next;
}node,*node_p;
typedef struct msg
{char type;char name[20];char text[128];
}msg;
node_p create_link()
{node_p H=(node_p)malloc(sizeof(node));if(H==NULL){printf("apply fail\n");return NULL;}H->next=NULL;return H;
}
node_p create_node(char *name,struct sockaddr_in cli_addr)
{node_p new=(node_p)malloc(sizeof(node));if(new==NULL){printf("apply fail\n");return NULL;}strcpy(new->name,name);new->cli_addr=cli_addr;new->next=NULL;return new;
}
void insert(node_p H,char *name,struct sockaddr_in cli_addr)
{if(H==NULL){printf("apply fail\n");return;}node_p new=create_node(name,cli_addr);new->next=H->next;H->next=new;
}
void delete(node_p H,char* name)
{if(H==NULL){printf("apply fail\n");return;}node_p p=H->next;while(p!=NULL&&strcmp(p->next->name,name)!=0){p=p->next;}node_p p1=p->next;p->next=p->next->next;free(p1);
}
int main(int argc, const char *argv[])
{if(argc!=3){printf("请依次输入正确的ip地址和端口号!\n");return 1;}const char *SER_IP=argv[1];int SER_PORT=atoi(argv[2]);int sfd=socket(AF_INET,SOCK_DGRAM,0); if(sfd==-1){perror("socket");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");return 1;}struct sockaddr_in cin;socklen_t addrlen=sizeof(cin);char wbuf[128]={0};struct pollfd pfd[2];pfd[0].fd=sfd;pfd[1].fd=0;pfd[0].events=POLLIN;pfd[1].events=POLLIN;node_p H=create_link();msg msg;printf("等待用户加入....\n");while(1){int res=poll(pfd,2,-1);if(res==-1){perror("poll");return 1;}else if(res==0){printf("time out\n");return 1;}if(pfd[0].revents==POLLIN){memset(&msg,0,sizeof(msg));recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&cin,&addrlen);if(msg.type=='n'){node_p p=H->next;insert(H,msg.name,cin);printf("*********\033[1;35m[%s\033[0m:\033[1;32m%d] \033[33m %s\033[0m\033[1;36m 已进入聊天室\033[0m*********** \n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),msg.name);while(p!=NULL){sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));p=p->next;}}else if(msg.type=='t'){node_p p=H->next;printf("%s:%s\n",msg.name,msg.text);while(p!=NULL){msg.type='t';if(strcmp(p->name,msg.name)!=0){sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));}p=p->next;}}else if(msg.type=='q'){printf("\033[1;36m%s离开了聊天室...\n",msg.name);node_p p=H->next;while(p!=NULL){msg.type='q';sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));p=p->next;}}}if(pfd[1].revents==POLLIN){msg.type='s';bzero(wbuf,sizeof(wbuf));fgets(wbuf,sizeof(wbuf),stdin);strcpy(msg.text,wbuf);msg.text[strlen(msg.text)-1]=0;node_p p=H->next;while(p!=NULL){msg.type='s';sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));p=p->next;}printf("\033[1;36m系统消息推送成功。\n");}}close(sfd);return 0;
}
客户端
#include <header.h>
int quit_flag=0;
typedef struct msg
{char type;char name[20];char text[128];
}msg;
int main(int argc, const char *argv[])
{if(argc!=3){printf("\033[1;35m请依次输入正确的ip地址和端口号!\n");return 1;}const char *SER_IP=argv[1];int SER_PORT=atoi(argv[2]);printf("\033[1;36m请输入用户名:");int cfd=socket(AF_INET,SOCK_DGRAM,0);if(cfd==-1){perror("socket");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 addrlen=sizeof(sin);struct pollfd pfd[2]; pfd[0].fd=0;pfd[1].fd=cfd;pfd[0].events=POLLIN;pfd[1].events=POLLIN;msg msg;char username[20]={0};fgets(username,sizeof(username),stdin);strcpy(msg.name,username);msg.name[strlen(msg.name)-1]=0;msg.type='n';sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));char rbuf[128]={0};while(1){int res=poll(pfd,2,-1);if(res==-1){perror("poll");return 1;}else if(res==0){printf("time out\n");return 1;}if(pfd[0].revents==POLLIN){msg.type='t';strcpy(msg.name,username);msg.name[strlen(msg.name)-1]=0;char txt[128]={0};bzero(txt,sizeof(txt));fgets(txt,sizeof(txt),stdin);strcpy(msg.text,txt);msg.text[strlen(msg.text)-1]=0;int flag=0;if(strcmp(msg.text,"quit")==0){msg.type='q';sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));flag=1;quit_flag=1;}if(flag==0){sendto(cfd,&msg,sizeof(msg),MSG_DONTWAIT,(struct sockaddr*)&sin,sizeof(sin));}}if(pfd[1].revents==POLLIN){recvfrom(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,&addrlen);if(msg.type=='t'){printf("\033[1;34m%s:\033[0m%s\n",msg.name,msg.text);}else if(msg.type=='n'){printf("-----------------\033[1;33m %s \033[1;35m 已上线 \033[1;33m--------------\n",msg.name);}else if(msg.type=='s'){printf("\033[1;36msystem:%s\n",msg.text);}else if(msg.type=='q'){printf("-----------------\033[1;33m %s\033[1;35m 已下线 \033[1;33m-------------\n",msg.name);if(quit_flag==1){break;}}}}close(cfd);exit(0);return 0;
}
功能实现