服务器端
#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;
}
功能实现