服务器端用来处理客户请求时采用了多线程。为每一个线程分配了一个处理信息的缓冲区。
/*定义线程缓冲区的使用状态*/
#define BUFF_OCCUPIED 1
#define BUFF_FREED 0
/*线程缓冲区结构*/
typedef struct thread_buff_struct_t {
/*线程缓冲区底索引号*/
int buff_index;
/*保存对应线程底线程号*/
int tid;
/*保存对应的客户机的IP地址*/
unsigned long ip_addr;
/*该线程使用的连接套接字描述符*/
int conn_fd;
/*线程缓冲区底状态*/
int buff_status;
}thread_buff_struct;
/*对于这么多缓冲区使用一个互斥量很少*/
thread_buff_struct thread_buff[THREAD_BUFF_NUM];
pthread_mutex_t buff_mutex;
/*初始化线程缓冲区*/
void init_thread_buff()
{
int index;
for(index=0;index<THREAD_BUFF_NUM;index++){
thread_buff[index].tid = -1;
thread_buff[index].buff_status = BUFF_FREED;
}
}
/*分配一个空闲的线程缓冲区,没有空闲的缓冲区则返回-1*/
int get_free_buff()
{
int i,ret;
pthread_mutex_lock(&buff_mutex);
for(i=0;i<THREAD_BUFF_NUM;i++)
if(thread_buff[i].buff_status == BUFF_FREED){
ret = i;
pthread_mutex_unlock(&buff_mutex);
break;
}
if(i == THREAD_BUFF_NUM){
ret = -1;
pthread_mutex_unlock(&buff_mutex);
}
return ret;
}
/*释放线程缓冲区,对buff_status的访问同样需要使用互斥保护*/
void free_buff(int index)
{
pthread_mutex_lock(&buff_mutex);
if(thread_buff[index].buff_status == BUFF_OCCUPIED)
thread_buff[index].buff_status == BUFF_FREED;
pthread_mutex_unlock(&buff_mutex);
}
/*检查线程缓冲区中是否有重复链接,因为可能客户端底通信进程重新启动,此时应该终止原来它所有的服务线程,再重新创建一个线程服务,并为这个新底服务线程分配线程缓冲区*/
void check_connection(unsigned long ip_addr)
{
int i,j;
struct in_addr in;
char msg[512];
/*检查所有底线程缓冲区*/
pthread_mutex_lock(&buff_mutex);
for(i=0;i<THREAD_BUFF_NUM;i++){
/*发现重复链接*/
if((thread_buff[i].buff_status!=BUFF_FREED)&&(thread_buff[i].ip_addr == ip_addr)){
in.s_addr = htonl(ip_addr);
sprintf(msg,"重复链接:%s,旧连接将关闭!\n",inet_ntoa(in));
add_info(msg);
pthread_cancel(thread_buff[i].tid);
pthread_join(thread_buff[i].tid,NULL);
/*退出的线程不释放它的缓冲区,释放工作由主线程来处理*/
thread_buff[i].tid = 0;
thread_buff[i].buff_status=BUFF_FREED;
close(thread_buff[i].conn_fd);
}
}
pthread_mutex_unlock(&buff_mutex);
}
关于线程缓冲区数组,我们只采用了一个互斥信号量,这是为了写起来方便。
项目代码下载地址:航空售票项目源码。有一些小BUG,还在继续改进。