#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
// 自定义头文件
#include "server_handler.h"
#include "protocol.h"
#include "process_protocol.h"
void * listenCommand(void * para_server_sockfd)
{
int server_sockfd=(int)para_server_sockfd;
char command[MAX_COMMAND_LEN+1];
// 监听服务器指令
while(1)
{
memset(command,0,MAX_COMMAND_LEN+1);
read(STDIN_FILENO,command,MAX_COMMAND_LEN);
command[strlen(command)-1]='\0';
if(strcmp(command,"exit")==0)
{
break;
}
}
// 加互斥锁
pthread_mutex_lock(&client_mutex);
// 关闭所有与客户端通信的socket
int i;
for(i=0;i<client_vector.capacity;i++)
{
if(client_vector.client_data[i].c_thread!=0)
{
close(client_vector.client_data[i].client_sockfd);
}
}
// 释放用户队列内存
free(client_vector.client_data);
// 关闭服务器socket
close(server_sockfd);
// 杀掉所有用户线程
for(i=0;i<client_vector.capacity;i++)
{
if(client_vector.client_data[i].is_used==USED)
{
if(pthread_cancel(client_vector.client_data[i].c_thread))
{
perror("Thread cancelation failed");
exit(EXIT_FAILURE);
}
}
}
// 解互斥锁
pthread_mutex_unlock(&client_mutex);
exit(EXIT_SUCCESS);
}
void acceptClient()
{
// 循环接受客户端连接请求
int client_sockfd;
int sin_size;
sin_size=sizeof(struct sockaddr_in);
while(1)
{
// 等待客户端连接请求到达
if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&remote_addr,(socklen_t*)&sin_size))<0)
{
perror("accept client socket failed");
exit(EXIT_FAILURE);
}
printf("accept client %s\n",inet_ntoa(remote_addr.sin_addr));
// 为每一个新用户创建一个线程来处理该用户的各种请求
createClientThread(client_sockfd);
}
}
void createCommandThread()
{
pthread_attr_t thread_attr;// 线程属性
// 初始化线程属性
if(pthread_attr_init(&thread_attr))
{
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
// 设置线程分离属性
if(pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED))
{
perror("Setting detach attribute failed");
exit(EXIT_FAILURE);
}
// 创建服务器命令监听线程
pthread_t command_thread;
if(pthread_create(&command_thread,&thread_attr,listenCommand,(void *)server_sockfd))
{
perror("command_thread creation failed");
exit(EXIT_FAILURE);
}
}
void createClientThread(int client_sockfd)
{
pthread_attr_t thread_attr;// 线程属性
// 初始化线程属性
if(pthread_attr_init(&thread_attr))
{
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
// 设置线程分离属性
if(pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED))
{
perror("Setting detach attribute failed");
exit(EXIT_FAILURE);
}
// 用户信息队列已满,重新申请更大空间的用户队列
if(client_vector.thread_num==client_vector.capacity)
{
int old_capacity=client_vector.capacity;
int new_capacity=2*old_capacity;
client_vector.capacity=new_capacity;
client_vector.client_data=(client*)realloc(client_vector.client_data,sizeof(client)*new_capacity);
// 内存分配失败
if(client_vector.client_data==NULL)
{
//... 发送给客户端一个错误提示包,提示用户重新登录或者稍后再试。
perror("client_vector remalloc failed");
exit(EXIT_FAILURE);
}
// 初始化新增的用户队列空间
int i;
for(i=old_capacity;i<new_capacity;i++)
{
client_vector.client_data[i].cid=i;
client_vector.client_data[i].c_thread=0;
client_vector.client_data[i].is_used=UNUSED;
client_vector.client_data[i].name[0]='\0';
}
}
// 遍历用户信息队列,找到闲置的pthread_t来创建该用户的登录线程
int i;
for(i=0;i<client_vector.capacity;i++)
{
if(client_vector.client_data[i].c_thread==0)
{
client_vector.client_data[i].client_sockfd=client_sockfd;
// 创建处理用户登录的线程
if(pthread_create(&client_vector.client_data[i].c_thread,&thread_attr,clientLogin,(void *)i))
{
perror("client thread creation failed");
exit(EXIT_FAILURE);
}
client_vector.thread_num++;
break;
}
}
}
void * clientLogin(void * para_cid)
{
// 设置线程允许取消状态
if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL))
{
perror("Thread pthread_setcancelstate failed");
exit(EXIT_FAILURE);
}
// 设置线程取消方式
if(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL))
{
perror("Thread pthread_setcanceltype failed");
exit(EXIT_FAILURE);
}
int cid=(int)para_cid;
int len;
int client_sockfd=client_vector.client_data[cid].client_sockfd;
p_base * p_base_ptr;
char buf[MAX_PACKET_LEN]={0};
while(1)
{
// 监听客户端发来的包
if((len=recv(client_sockfd,buf,MAX_PACKET_LEN,0))>0)
{
p_base_ptr=(p_base*)buf;
protocol_handler_array[p_base_ptr->p_name](p_base_ptr,cid);
}
// 客户端断开连接
else
{
// 删除该用户
deleteClient(cid);
break;
}
}
// 退出该用户线程
pthread_exit(NULL);
// 关闭该用户的socket
close(client_sockfd);
}
void init()
{
// 初始化互斥量
if(pthread_mutex_init(&client_mutex,NULL))
{
perror("initialize client_mutex failed");
exit(EXIT_FAILURE);
}
// 设置服务器网络地址
memset(&server_addr,0,sizeof(server_addr)); // 数据初始化--清零
server_addr.sin_family=AF_INET; // 设置为IP通信
server_addr.sin_addr.s_addr=INADDR_ANY;// 服务器IP地址--允许连接到所有本地地址上
server_addr.sin_port=htons(12000); // 服务器端口号
// 创建服务器端套接字--IPv4协议,面向连接通信,TCP协议
if((server_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)
{
perror("server socket creation failed");
exit(EXIT_FAILURE);
}
// 设置地址可以立即被重用
int on=1;
if(setsockopt(server_sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))
{
perror("setsockopt--set address reused failed");
exit(EXIT_FAILURE);
}
// 将套接字绑定到服务器的网络地址上
if(bind(server_sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr))<0)
{
perror("socket bind failed");
exit(EXIT_FAILURE);
}
// 监听连接请求--监听队列长度为5
listen(server_sockfd,5);
// 初始化用户队列
client_vector.client_data=(client*)malloc(sizeof(client)*INIT_CLIENT_NUM);
client_vector.capacity=INIT_CLIENT_NUM;
client_vector.size=0;
client_vector.thread_num=0;
int i;
for(i=0;i<INIT_CLIENT_NUM;i++)
{
client_vector.client_data[i].c_thread=0;
client_vector.client_data[i].is_used=UNUSED;
client_vector.client_data[i].cid=i;
client_vector.client_data[i].name[0]='\0';
}
// 初始化协议处理函数队列
protocol_handler_array[P_CS_LOGIN]=onCSLogin;
protocol_handler_array[P_CS_MESSAGE]=onCSMessage;
}
int deleteClient(int cid)
{
p_sc_client_logout packet;
packet.cid=cid;
// 加互斥锁
pthread_mutex_lock(&client_mutex);
int i;
for(i=0;i<client_vector.capacity;i++)
{
if(client_vector.client_data[i].is_used==USED)
{
// 通知其他用户,该用户下线了
if(i!=cid)
{
send(client_vector.client_data[i].client_sockfd,&packet,packet.p_len,0);
}
// 在用户队列中找到该下线用户
else
{
// 在服务器端打印用户下线信息
printf("%s logout.\n",client_vector.client_data[i].name);
// 将该用户从服务器端的用户队列中删除
client_vector.client_data[i].client_sockfd=-1;
client_vector.client_da
- 1
- 2
- 3
- 4
- 5
- 6
前往页