服务器端:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT 8888
#define IP "192.168.31.83"
struct sockaddr_in ser_addr,cli_addr;
typedef struct node
{
struct sockaddr_in addr;
struct node* next;
}list;
struct MSG
{
char type;
char name[10];
char text[128];
}msg,msg_send;
//创建节点
list* list_create()
{
list* l=(list*)malloc(sizeof(list));
if(NULL == l)
{
printf("创建失败");
return NULL;
}
l->next = NULL;
return l;
}
int insert(list* l,struct sockaddr_in addr)
{
if(NULL == l)
{
return -1;
}
list* pnew=(list*)malloc(sizeof(list));
pnew->addr=addr;
list*ptmp=l;
while(ptmp->next!=NULL)
{
ptmp=ptmp->next;
}
ptmp->next=pnew;
return 0;
}
//接收登录请求并发送
void do_login(int sfd,struct MSG msg,list* l,struct sockaddr_in cli_addr)
{
printf("----%s上线----\n",msg.name);
insert(l,cli_addr);
list* p = l->next;
while(p!= NULL)
{
msg.type='l';
sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->addr,sizeof(p->addr));
p=p->next;
}
return;
}
//聊天信息接收并发送
void do_chat(int sfd,struct MSG msg,list* t,struct sockaddr_in cli_addr)
{
if(strcmp(msg.name,"管理员")!=0)
{
printf("[%s] : %s\n",msg.name,msg.text);
}
list* p=t->next;
while(p!=NULL)
{
msg.type = 'c';
if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->addr,sizeof(p->addr))<0)
{
perror("sendto");
}
p=p->next;
}
return;
}
//退出聊天
void do_quit(int sfd,struct MSG msg,list* l,struct sockaddr_in cli_addr)
{
list* t = l;
printf("----%s离线----\n",msg.name);
list* pdel=NULL;
while(t->next!=NULL)
{
msg.type='q';
if(0==memcmp(&(t->next->addr),&cli_addr,sizeof(cli_addr)))
{
pdel=t->next;
t->next=pdel->next;
free(pdel);
pdel=NULL;
}else
{
t=t->next;
if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&t->addr,sizeof(t->addr))<0)
{
perror("sendto");
}
}
}
return;
}
//系统发送消息
void* callback(void* arg)
{
int sfd=*(int*)arg;
while(1)
{
msg_send.type='c';
strcpy(msg_send.name,"管理员");
memset(msg_send.text,0,128);
fgets(msg_send.text, 128, stdin);
msg_send.text[strlen(msg_send.text)-1]=0;
if(sendto(sfd, &msg_send, sizeof(msg_send), 0,(struct sockaddr*)&ser_addr, sizeof(ser_addr))< 0)
{
perror("sendto");
return NULL;
}
}
}
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0)
{
perror("socket");
return -1;
}
//填充网络信息结构体
memset(&ser_addr,0,sizeof(ser_addr));
ser_addr.sin_family =AF_INET;
ser_addr.sin_port =htons(PORT);
ser_addr.sin_addr.s_addr =inet_addr(IP);
socklen_t addrlen = sizeof(ser_addr);
socklen_t c_addrlen = sizeof(cli_addr);
//绑定
if(bind(sfd,(struct sockaddr*)&ser_addr,addrlen)<0)
{
perror("bind");
return -1;
}
pthread_t tid;
if(pthread_create(&tid,NULL,callback,(void*)&sfd)!=0)
{
perror("pthread_create");
return -1;
}
list* l=list_create();
while(1)
{
//接收客户端信息
memset(&msg,0,sizeof(msg));
if(recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&cli_addr,&c_addrlen)<0)
{
perror("recvfrom");
return -1;
}
switch(msg.type)
{
case 'l':
do_login(sfd,msg,l,cli_addr);
break;
case 'c':
do_chat(sfd,msg,l,cli_addr);
break;
case 'q':
do_quit(sfd,msg,l,cli_addr);
break;
}
}
pthread_join(tid,NULL);
return 0;
}
客户端:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT 8888
#define IP "192.168.31.83"
struct MSG
{
char type;
char name[10];
char text[128];
}msg,msg_send;
int sfd;
char buf[10]={0};
struct sockaddr_in ser_addr;
//接收服务器信息
void* callback(void* arg)
{
socklen_t addrlen=*((socklen_t*)arg);
while(1)
{
memset(&msg,0,sizeof(msg));
if(recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&ser_addr,&addrlen)<0)
{
perror("recvfrom");
return NULL;
}
if(strcmp(buf,msg.name)==10)
{
//printf("%d",strcmp(buf,msg.name));
continue;
}else{
switch(msg.type)
{
case 'l':
printf("----%s上线----\n",msg.name);
break;
case 'c':
printf("[%s] : %s\n",msg.name,msg.text);
break;
case 'q':
printf("----%s下线-----\n",msg.name);
break;
}
}
}
}
int main(int argc, const char *argv[])
{
sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0)
{
perror("socket");
return -1;
}
ser_addr.sin_family =AF_INET;
ser_addr.sin_port =htons(PORT);
ser_addr.sin_addr.s_addr =inet_addr(IP);
socklen_t addrlen=sizeof(ser_addr);
printf("请输入名字>>");
msg_send.type='l';
memset(msg_send.name,0,10);
fgets(buf,10,stdin);
strcpy(msg_send.name,buf);
msg_send.name[strlen(msg_send.name)-1]=0;
if(sendto(sfd,&msg_send,sizeof(msg_send),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr))<0)
{
perror("sendto");
return -1;
}
pthread_t tid;
if(pthread_create(&tid,NULL,callback,(void*)&addrlen)!=0)
{
perror("pthread_create");
return -1;
}
while(1)
{
memset(msg_send.text,0,128);
fgets(msg_send.text,128,stdin);
msg_send.text[strlen(msg_send.text)-1]=0;
if(strcmp(msg_send.text,"quit")==0)
{
msg_send.type='q';
sendto(sfd,&msg_send,sizeof(msg_send),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
exit(0);
}else{
msg_send.type='c';
}
if(sendto(sfd,&msg_send,sizeof(msg_send),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr))<0)
{
perror("sendto");
return -1;
}
}
pthread_join(tid,NULL);
return 0;
}