//服务端代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include<string.h>
#include<pthread.h>
#include "head.h"
//定义链表节点结构体
typedef struct node_t
{
struct sockaddr_in caddr;
struct node_t *next;
} list_t;
struct sockaddr_in serveraddr, caddr;
list_t *createList(void);
void *thread(void*arg);
void login_server(int sockfd,MSG_t msg,list_t*p,struct sockaddr_in addr);
void chat_server(int sockfd,MSG_t msg,list_t *p,struct sockaddr_in addr);
void quit_server(int sockfd,MSG_t msg,list_t*p,struct sockaddr_in addr);
int main(int argc, char const *argv[])
{
//1.创建数据报套接子
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("socket err.");
return -1;
}
struct sockaddr_in serveraddr, caddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[1]));
serveraddr.sin_addr.s_addr = inet_addr("0.0.0.0");
socklen_t len = sizeof(caddr);
//2.绑定
if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind err.");
return -1;
}
pthread_t tid;
pthread_create(&tid, NULL, thread, &sockfd);
pthread_detach(tid);
//3.循环接受客户端的请求
MSG_t msg;
int r;
list_t *p = createList();
while (1)
{
r=recvfrom(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&caddr,&len);
if(r<0)
{
perror("recv err");
return -1;
}
switch(msg.type)
{
case Login:
login_server(sockfd,msg,p,caddr);
break;
case Chat:
chat_server(sockfd,msg,p,caddr);
break;
case Quit:
quit_server(sockfd,msg,p,caddr);
break;
}
}
close(sockfd);
return 0;
}
list_t *createList(void)
{
list_t *p=(list_t*)malloc(sizeof(list_t));
if(p==NULL)
{
perror("malloc err");
return NULL;
}
p->next = NULL;
return p;
}
//登录
void login_server(int sockfd,MSG_t msg,list_t*p,struct sockaddr_in addr)
{
sprintf(msg.text,"%s client login",msg.name);
while(p->next!=NULL)
{
p=p->next;
sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&(p->caddr),sizeof(p->caddr));
}
list_t *pnew=(list_t*)malloc(sizeof(list_t));
if(pnew==NULL)
{
perror("malloc new node err");
return;
}
pnew->caddr=addr;
pnew->next=NULL;
p->next=pnew;
return;
}
//聊天
void chat_server(int sockfd,MSG_t msg,list_t *p,struct sockaddr_in addr)
{
//1.遍历链接
while(p->next!=NULL)
{
p=p->next;
if(memcmp(&(p->caddr),&addr,sizeof(addr))!=0)
{
sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&(p->caddr),sizeof(p->caddr));
}
}
return; ;
}
//3.退出
void quit_server(int sockfd,MSG_t msg,list_t*p,struct sockaddr_in addr)
{
list_t*pdel=NULL;
sprintf(msg.text,"%s client exit",msg.name);
while (p->next!=NULL)
{
if(memcmp(&(p->next->caddr),&addr,sizeof(addr)))
{
p=p->next;
sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&(p->caddr),sizeof(p->caddr));
}
else
{
pdel=p->next;
p->next=pdel->next;
free(pdel);
pdel=NULL;
}
}
return;
}
void *thread(void*arg)
{
MSG_t msg_s;
int sockfd=*((int*)arg);
msg_s.type=Chat;
strcpy(msg_s.name,"server");
while(1)
{
fgets(msg_s.text,sizeof(msg_s.text),stdin);
if(msg_s.text[strlen(msg_s.text)-1]=='\n')
msg_s.text[strlen(msg_s.text)-1]='\0';
sendto(sockfd, &msg_s, sizeof(msg_s), 0,
(struct sockaddr *)&serveraddr, sizeof(serveraddr));
}
pthread_exit(NULL);
}