linux下用线程实现的聊天室 服务器部分

来源:互联网 发布:中山陵哭陵事件 知乎 编辑:程序博客网 时间:2024/06/05 10:53

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <sqlite3.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>

#define PORT 9071//定义的端口号为 9071
#define BUFF_MAX 1024//缓冲器的最大长度
#define MSG_MAX 924//msg的最大长度
#define LISENT_BACK 10

        /*<普通用户>*/
#define HELP 1          //帮助信息显示
#define LOG 2           //登录
#define REG 3           //注册
#define PTO 4           //悄悄话
#define CTO 5          //群发消息
#define VIM 6           //查看在线用户
#define VOM 7         //查看所有用户
#define CAT 8          //查看聊天历史记录
#define FAC 9          //特殊表情
#define ESC 10        //退出

    /*<超级管理员>*/
#define KIC 11         // 踢人
#define SCL 12        //禁言
#define RCL 13        //撤销禁言


int servsock_fd;//定义一个全局变量来保存客户端sock地址


struct man //用于注册信息的结构体
{
    char name[20];
    char passward[20];

};
struct sockfd_lis//用于存放新创建fd,和登录的用户名
{
    pthread_t sock_fd;
    char name[20];
    char msg[MSG_MAX];
    struct sockfd_lis *next;
};
struct msg_chat//用于存放客户端发送的动作
{
    int action[1];
    char name[20];
};
int flag = 0;
typedef struct sockfd_lis * line;
line head;
/*********************************************************************************************************************/
void  friend_num(int x,char num[])//将整型转换为字符型
{
    printf("..friend_num1\n");
    int i = 0;
    int j = x;
    while(j != 0)
    {
        j = j/10;
        i++;
    }
    while(i+1!= 0)
    {
      num[(i--)-1] = x%10 + '0';
      x = x/10;
    }
      printf("..friend_num0\n");
      return;
}
/*********************************************************************************************************************/
/*链表部分的程序*/
/*创建链表,用于存放新创建线程,和登录的用户名*/
line creat_lin(line *head)
{
    printf("..creat_lin1\n");
    *head = NULL;
    printf("..creat_lin0\n");   
    return *head;
}
/*尾部插入链表*/
int end_insert(line *head,line *newnode)
{
    printf("..end_insert1\n");
    if(*newnode == NULL)
    {
        printf("..end_insert0\n");
        return 0;
    }
    if(*head == NULL)
    {
        (*newnode)->next = NULL;
        *head = *newnode;
        printf("..end_insert0\n");        
        return 1;
    }
    line temp = *head;
    while(temp->next != NULL)
    {
         temp = temp->next;
    }
    temp->next = *newnode;
    (*newnode)->next = NULL;
    printf("..end_insert0\n");   
    return 1; 
}
/*查找指定在线用户sock_fd*/
int find_lin(line *head,char* name)
{
    printf("..find_lin1\n");
    line temp = *head;
    while(temp != NULL)
    {
        if(0 == strcmp(temp->name,name))
        { 
            printf("pthread id is %d", temp->sock_fd);
            printf("..find_lin0\n");
            return temp->sock_fd;       
        }
       temp = temp->next;     
    }
    printf("..find_lin0\n");    
    return 0;
}
/*指定在线用户存储信息*/
void find_lin_msg(line *head,pthread_t sock_fd,char msg[])
{
    printf("..find_lin_msg1\n");
    line temp = *head;
    while(temp != NULL)
    {
        if(pthread_equal(sock_fd,temp->sock_fd))
        { 
            strcpy(temp->msg,msg);  
        }
       temp = temp->next;     
    }
    printf("..find_lin_msg0\n");    
    return;
}
/*用户下线,删除该用户所在结点*/
int delete_lin(line *head,char* name)
{
    printf("..delete_lin1\n");
    if(*head == NULL)
    {
    printf("..delete_lin0\n");    
        return 0;
    }
    line temp = *head;   
    if(0 == strcmp((*head)->name,name))//删除点在头部
    {
        line temp = *head;
        *head = (*head)->next;
        free(temp);
        temp = NULL;
        printf("..delete_lin0 head\n"); 
        return 1;
    }
    line ptr = temp;
    temp = temp->next;
    while(temp!= NULL)//删除点在中间
    {
        if(0 == strcmp(temp->name,name))
          {
              ptr->next = temp->next;
              free(temp);
              temp = NULL;
              printf("..delete_lin0 middle\n"); 
              return 1;
          }           
          ptr = temp;
          temp = temp->next;
    }
    printf("..delete_lin0\n");     
    return 0;     
}
/*输出链表*/
void display_lin(line * head)
{
    printf("..display_lin1\n"); 
    line temp = * head;
    while(temp != NULL)
    {
        printf("%s\n",temp->name);
        temp = temp ->next;   
    }
    printf("..display_lin0\n"); 
    return;
}
/*显示在线用户*/
void display_lin_vim(line * head,char buffer[])
{
    printf("..display_lin_vim1\n"); 
    line temp = * head;
    bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
    strcpy(buffer,"当前在线用户有:\n");
    while(temp != NULL)
    {
        strcat(buffer,temp->name);
        strcat(buffer,"\n");
        temp = temp ->next;   
    }
    printf("..display_lin_vim0\n");
    return;
}
/*获取cto_fd*/
void display_lin_cto(line * head,char buffer[])
{
    printf("..display_lin_cto1\n");    
    ssize_t write_fd;//存放读和写的描述符
    line temp = * head;
    while(temp != NULL)
    {
   write_fd = write(temp->sock_fd,buffer,BUFF_MAX);
   if(-1 == write_fd)
   {
    perror("write");
    exit(EXIT_FAILURE);   
   }
        temp = temp ->next;   
    }
    printf("..display_lin_cto0\n");     
    return;
}
/**************************************************************************************************************/
/*************************************************************************************************************/
/////////////////////////////////////////////////////<chat_log登录>////////////////////////////////////////////////////////
void chat_log(int sock_fd,struct man *id)
{
    printf("log!\n");
    printf("state-> %d: ",LOG);
    sqlite3*db = NULL;//定义一个数据库文件
    char **result = NULL;//定义一个存放字符串的数组保存查询结果
    char *errmsg = NULL;//定义保存错误信息
    int rc;//数据库函数的返回值
    int row;//需要查找的行
    int column;//需要查找的列
    char sql[BUFF_MAX];//数据库操作的字符串
    char buffer[BUFF_MAX] ={0};//缓冲区
    line newnode;//该指针用于添加新用户于链表
    line temp;//用于遍历链表
    ssize_t write_fd,read_fd;//读和写的描述符
    /*开始登录*/
                     /*读用户信息*/
                        printf("读用户名\n");
    read_fd = read(sock_fd, (*id).name, (size_t)BUFF_MAX);//读用户名
    if(-1 == read_fd)
    {
     perror("read");
     exit(EXIT_FAILURE);  
    }
    printf("name is %s\n",(*id).name);
    printf("读密码\n");
    read_fd = read(sock_fd,(*id).passward, (size_t)BUFF_MAX);//读密码
    if(-1 == read_fd)
    {
     perror("read");
     exit(EXIT_FAILURE);  
    }
     printf("passward input down\n");
                        /*服务器反应部分*/
                        char *a[1] = {0}; 
                                                            
    rc = sqlite3_open("serve_data.db", &db);
    printf("查询数据库中的该用户\n");
    sprintf(sql, "select * from user_table where name='%s'", (*id).name);//查询数据库中的该用户
    rc = sqlite3_get_table(db, sql, &result, &row, &column, &errmsg);    
  //<o用户o>// 
              if (0 != strcmp(result[0],"name")) /* 检查是否在数据库中找到该用户 */
                                   {
                       strcpy(buffer, "用户未注册请先注册\n");
                       printf("%s",buffer);
                       write_fd = write(sock_fd, buffer,sizeof(buffer));
        if(-1 == write_fd)
        {
            perror("write");
            exit(EXIT_FAILURE);
               } 
               memset(buffer,0,sizeof(buffer));//清空缓存中的内容
               sqlite3_free_table(result);
                                        sqlite3_close(db);
                                        printf("log out!\n");
               return;
                      } 
                  if (strcmp((*id).passward, result[3]) != 0)/*检查用户密码是否输入正确*/
                       {
                         bzero(buffer, sizeof(buffer)); //清空缓冲区
               strcpy(buffer, "密码错误");
               write_fd = write(sock_fd, buffer,sizeof(buffer));
                if(-1 == write_fd)
           {
        perror("write");
        exit(EXIT_FAILURE);
            }
           memset(buffer,0,sizeof(buffer));//清空缓存中的内容
             sqlite3_free_table(result);
                                                sqlite3_close(db);
                                                printf("log out!\n");  
             return;                    
                        }     
               else
                    {
                /* 检查是否已经登录*/
               if(find_lin(&head,(*id).name))
                  {
                  //  memset(buffer, 0, BUFF_MAX);//初始化
                                   bzero(buffer, sizeof(buffer)); //清空缓冲区                  
                    strcpy(buffer, "你的帐号已登录,不能重复登录\n");
                    printf("%s",buffer);
                    write_fd = write(sock_fd, buffer,sizeof(buffer));
               if(-1 == write_fd)
                {
            perror("write");
            exit(EXIT_FAILURE);
                        }
                    memset(buffer,0,sizeof(buffer));//清空缓存中的内容
                                                  sqlite3_free_table(result);
                                                  sqlite3_close(db);
                                                  printf("log out!\n");   
                    return;
                  }                                    
                    } 
                                       /*登录成功*/
           printf("%s\n",(*id).name);
           //memset(buffer, 0, BUFF_MAX);//初始化
                  bzero(buffer, sizeof(buffer)); //清空缓冲区
                  if(0 == strcmp((*id).name,"admin"))
                     {
                         strcpy(buffer, "超级管理员成功登录\n");
                     }
                  if(0 != strcmp((*id).name,"admin"))
                     {
             strcpy(buffer, "登录成功\n");
              }
             printf("%s",buffer);
             write_fd = write(sock_fd, buffer,sizeof(buffer));
             if(-1 == write_fd)
              {
          perror("write");
          exit(EXIT_FAILURE);
               }  
        int ter = open("serve_log.txt", O_RDWR|O_CREAT|O_APPEND, S_IRUSR);
         if(-1 == ter)
       {
           perror("open");
           exit(EXIT_FAILURE);
        }
                    strcpy(buffer, (*id).name);
                    strcat(buffer, "于");
                    time_t t;
                    time(&t);
                    strcat(buffer, ctime(&t));
                    strcat(buffer, " 成功登录\n");
                         
          write(ter,buffer,(size_t)(strlen(buffer)));
          if( -1 == ter)
          {
              perror("write");
         exit(EXIT_FAILURE);      
          }
              bzero(buffer, sizeof(buffer)); //清空缓冲区

        
         /*将成功登录的用户加入链表*/
         if((newnode = (line)malloc (sizeof(struct sockfd_lis))) == 0)//给新结点分配空间
         {
        printf("malloc error!\n");
        exit(EXIT_FAILURE);
          }
         if(end_insert(&head,&newnode) == 0)//在链表中添加新结点
          {
        printf("insert error");
        exit(EXIT_FAILURE);
         }
                             strcpy(newnode-> name, (*id).name);//登录的用户名
                             newnode-> sock_fd = sock_fd;//客户端
                             printf("显示当前在现用户\n");
                             display_lin(&head);
         memset((struct sockaddr_in*)&buffer, 0, sizeof(buffer));//清空缓存     
        
                                       sqlite3_free_table(result);
                                       sqlite3_close(db); 
    printf("log out!\n");                                                     
    return;
}
/////////////////////////////////////////////////<chat_log登录>//////////////////////////////////////////////////////////
//////////////////////////////////////////////////<chat_reg注册>////////////////////////////////////////////////////////
void chat_reg(int sock_fd,struct man *id)
{
      printf("reg!\n");
 printf("state ->%d: ",REG);
 static sqlite3 *db = NULL;//定义一个数据库文件
 static char *errmsg = NULL;//定义用来保存错误的信息
 int rc;//数据库函数返回值
 char sql[BUFF_MAX];//数据库操作字符串
 char buffer[BUFF_MAX] ={0};//定义缓冲区
 ssize_t write_fd,read_fd;//写的描述符

 /*开始注册*/
                                            /*读用户信息*/     
    read_fd = read(sock_fd, (*id).name, (size_t)BUFF_MAX);//读用户名
    if(-1 == read_fd)
    {
     perror("read");
     exit(EXIT_FAILURE);  
    } 
    printf("name is %s\n", (*id).name);
    read_fd = read(sock_fd,(*id).passward, (size_t)BUFF_MAX);//读密码
    if(-1 == read_fd)
    {
     perror("read");
     exit(EXIT_FAILURE);  
    }
    printf("passward input down\n");
               /*在数据库之中插入新用户和密码*/
         rc = sqlite3_open("serve_data.db",&db);//创建一个名为sreve_data.db的数据库文件
    if (rc)
    {
     strcpy(buffer, "error in creat serve_data.db!\n");
     printf("reg out!\n");     
     return;
    }
    //sprintf(sql,"create table user_table(name text, password text,primary key(name))");//给sql语句赋值创建表类型
    /*rc = sqlite3_exec(db,sql,0,0,&errmsg);//数据库创建表
    if (rc)
    {
     strcpy(buffer, "error in creat user_table!\n");
     printf("reg out!\n"); 
     return;
    }  */ 
    sprintf(sql,"insert into user_table values('%s','%s')",(*id).name,(*id).passward); 
    printf("%s insert ",(*id).name);
                        rc = sqlite3_exec(db,sql,0,0,&errmsg);//插入数据         
    if (rc)//如果用户已存在
    {
     printf("error!\n");
          memset(buffer, 0, BUFF_MAX);//初始化
     strcpy(buffer, "该用户已经存在,请您更换其他的用户名!\n");
     write_fd = write(sock_fd, buffer,sizeof(buffer));
     if(-1 == write_fd)
     {
      perror("write");
      exit(EXIT_FAILURE);
     }
    }
    else//注册成功
    {   
     printf("%s reg successful!\n",(*id).name);
     memset(buffer, 0, BUFF_MAX);//初始化
     strcpy(buffer,"注册成功,请您登录!\n");
     write_fd = write(sock_fd, buffer,sizeof(buffer));
     if(-1 == write_fd)
     {
      perror("write");
      exit(EXIT_FAILURE);
     }
    }
    sqlite3_close(db);
    printf("reg out!\n");   
    return;    
}
//////////////////////////////////////////////////<chat_reg注册>//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////<chat_pto私聊>////////////////////////////////////////////////////////////////
void chat_pto(int sock_fd,struct man *id)
{
    printf("pto!\n");
    printf("state ->%d: ",PTO);
   
    ssize_t read_fd, write_fd;//存放读和写的描述符
    struct msg_chat action;//用来存放动作
    char pto_name[20];//用于存放接收消息的用户
    char buffer[BUFF_MAX] = {0};//用于存放接收的信息
    char msg[MSG_MAX] = {0};//用于存放信息
    pthread_t pto_fd;//用于存放接收用户的套接口描述符
    action.action[0] = PTO; 
    int onlin[1] = {0};
        /*开始私聊*/
                        printf("%s to ",(*id).name);
    read_fd = read(sock_fd,pto_name,20);//读取客户端发来的用户名
    if (-1 == read_fd)
    {
     perror("write");
     exit(EXIT_FAILURE);
    }
    printf("%s\n",pto_name);
    pto_fd = find_lin(&head,pto_name);//获取该用户线程的描述符
  
    if(0 == pto_fd)//不在线
    {
           bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
           strcpy(buffer,"该用户不在线,不能发送消息\n");
           printf("%s\n",buffer);
           write_fd = write(sock_fd,buffer,sizeof(buffer));
      if(-1 == write_fd)
     {
      perror("write");
      exit(EXIT_FAILURE);    
     } 
     memset(buffer,0,sizeof(buffer));//清空缓存中的内容 
      printf("pto out!\n");        
           return;
    }
    if(pto_fd)
    {   
     read_fd = read(sock_fd,msg,MSG_MAX);//接收用户端发来的消息
     if(-1 == read_fd)
     {
           perror("read");
           exit(EXIT_FAILURE);
     }
     printf("%s\n",buffer);
     
     bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
     strcpy(buffer,"\nrecive a massage!");   
          time_t t;
          time(&t);
          strcat(buffer, ctime(&t));
          //strcat(buffer,"\n");  
     strcat(buffer,(*id).name);
     strcat(buffer, "悄悄说->:");
     strcat(buffer,msg);
     strcat(buffer,"\n");
     printf("%s",buffer);    
     write_fd = write(pto_fd,buffer,sizeof(buffer));
     if(-1 == write_fd)
     {
         perror("write");
         exit(EXIT_FAILURE);   
     }
     
     int ter = open("chat.txt", O_RDWR|O_CREAT|O_APPEND, S_IRUSR);
     if(-1 == ter)
           {
           perror("open");
           exit(EXIT_FAILURE);
           }
          
          write(ter,buffer,(size_t)(strlen(buffer)));
     if( -1 == ter)
     {
       perror("write");
      exit(EXIT_FAILURE);      
           }
     memset(buffer,0,sizeof(buffer));//清空缓存中的内容
    } 
    printf("pto out!\n");
    return;
}
//////////////////////////////////////////////////<chat_pto私聊>////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////<chat_cto公聊>////////////////////////////////////////////////////////////////
void chat_cto(int sock_fd,struct man *id)
{
    printf("cto!\n");
    printf("state ->%d: ",CTO);
   
    ssize_t read_fd, write_fd;//存放读和写的描述符
    struct msg_chat action;//用来存放动作
    char buffer[BUFF_MAX] = {0};//用于存放接收的信息
    char msg[MSG_MAX] = {0};//用于存放信息
    action.action[0] = CTO; 
    int onlin[1] = {0};
        /*开始公聊*/
                        printf("%s  ",(*id).name);
                        bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */            
      read_fd = read(sock_fd,msg,MSG_MAX);//接收用户端发来的消息
    if(-1 == read_fd)
    {
          perror("read");         
          exit(EXIT_FAILURE);
    }
    printf("%s\n",buffer);
         strcpy(buffer,"recive a massage!");
         time_t t;
    time(&t);
    strcat(buffer, ctime(&t));
    //strcat(buffer,"\n");    
    strcat(buffer,(*id).name);
    strcat(buffer, "对大家说->:");
    strcat(buffer,msg);
    strcat(buffer,"\n");
    printf("%s",buffer);    
    //display_lin_cto(&head,buffer);
    ////////////////////////////
        line temp = head;
        while(temp != NULL)
        {
       write_fd = write(temp->sock_fd,buffer,sizeof(buffer));
       if(-1 == write_fd)
       {
        perror("write");
        exit(EXIT_FAILURE);   
       }
            temp = temp ->next;   
        }
    ////////////////////////////
    int ter = open("chat.txt", O_RDWR|O_CREAT|O_APPEND, S_IRUSR);
    if(-1 == ter)
    {
          perror("open");
          exit(EXIT_FAILURE);
          }         
         write(ter,buffer,(size_t)(strlen(buffer)));
    if( -1 == ter)
    {
      perror("write");
     exit(EXIT_FAILURE);      
          }       
    memset(buffer,0,sizeof(buffer));//清空缓存中的内容
    
    printf("cto out!\n");     
    return;
}
//////////////////////////////////////////////////<chat_cto公聊>////////////////////////////////////////////////////////////////
/////////////////////////////////////////////<chat_vim显示在线用户>///////////////////////////////////////////////////////
void chat_vim(int sock_fd,struct man * id)
{
    printf("vim!\n");
    printf("state ->%d: ",VIM);
    char buffer[BUFF_MAX] = {0};//用于存放接收的信息
    ssize_t read_fd, write_fd;//存放读和写的描述符
   
    bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
    display_lin_vim(&head,buffer);
    write_fd = write(sock_fd,buffer,sizeof(buffer));
    if(-1 == write_fd)
    {
        perror("write");
        exit(EXIT_FAILURE);   
    }
   memset(buffer,0,sizeof(buffer));//清空缓存中的内容
   printf("vim out!\n");
   return;
}
//////////////////////////////////////////////<chat_vim显示在线用户>//////////////////////////////////////////////////////
//////////////////////////////////////////////<chat_vom显示所有用户>/////////////////////////////////////////////////////
void chat_vom(int sock_fd,struct man * id)
{
    printf("vom!\n");
    printf("state ->%d: ",VOM);
    sqlite3*db = NULL;//定义一个数据库文件
    char **result = NULL;//定义一个存放字符串的数组保存查询结果
    char *errmsg = NULL;//定义保存错误信息
    int rc;//数据库函数的返回值
    int row;//需要查找的行
    int column;//需要查找的列
    char sql[BUFF_MAX];//数据库操作的字符串
    char num[1024] = {0};
    int i = 1;
   
    char buffer[BUFF_MAX] = {0};//用于存放接收的信息
    ssize_t read_fd, write_fd;//存放读和写的描述符  
    bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
        rc = sqlite3_open("serve_data.db", &db); 
   
    sprintf(sql, "select * from user_table");//查询数据库中的该用户
    rc = sqlite3_get_table(db, sql, &result, &row, &column, &errmsg);
    friend_num(row,num);
    strcpy(buffer,"您共有好友数为");
    strcat(buffer,num);
    strcat(buffer,"\n");
    for(i = 2;i < row * column+2;i =  i+2)
    {
         printf("%s\n",result[i]);
         strcat(buffer,result[i]);
         strcat(buffer,"\n"); 

    }    
    write_fd = write(sock_fd,buffer,sizeof(buffer));
    if(-1 == write_fd)
    {
        perror("write");
        exit(EXIT_FAILURE);   
    }
    memset(buffer,0,sizeof(buffer));//清空缓存中的内容
    printf("vom out!\n");
    return;
}
//////////////////////////////////////////////<chat_vom显示所有用户>/////////////////////////////////////////////////////
///////////////////////////////////////////////////<chat_kic踢人>////////////////////////////////////////////////////////////////
void chat_kic(int sock_fd,struct man * id)
{
        printf("kic!\n");
        printf("state ->%d: ",KIC);
        ssize_t read_fd, write_fd;//存放读和写的描述符
        char kic_name[20] = {0};
        int kic_fd;
        char buffer[BUFF_MAX] = {0};//用于存放发送的信息
        read_fd = read(sock_fd,kic_name, 20);//所踢人的姓名 
        if (-1 == read_fd)
         {
  perror("read");
  exit(EXIT_FAILURE);
         } 
          bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
          strcpy(buffer,"该人已经被踢下线\n");
          write_fd = write(sock_fd,buffer,BUFF_MAX);//
       if (-1 == write_fd)
       {
  perror("write");
  exit(EXIT_FAILURE);
       }  
          bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
          kic_fd =  find_lin(&head,kic_name);
          strcpy(buffer,"你已经被踢下线\n");
          write_fd = write(kic_fd,buffer,BUFF_MAX);//
       if (-1 == write_fd)
       {
  perror("write");
  exit(EXIT_FAILURE);
       }                     
       delete_lin(&head,kic_name);        
       memset(kic_name,0,sizeof(kic_name));//清空缓存中的内容
       printf("显示当前在现用户\n");
  display_lin(&head);
    printf("kic out!\n");
    return;
}
///////////////////////////////////////////////////<chat_kic踢人>////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////<chat_scl禁言>////////////////////////////////////////////////////////////////
void chat_scl(int sock_fd,struct man * id)
{
        printf("scl!\n");
        printf("state ->%d: ",SCL);
        ssize_t read_fd, write_fd;//存放读和写的描述符
        char scl_name[20] = {0};
        int scl_fd;
        char buffer[BUFF_MAX] = {0};//用于存放发送的信息
        read_fd = read(sock_fd,scl_name, 20);//所禁言人的姓名 
        if (-1 == read_fd)
         {
  perror("read");
  exit(EXIT_FAILURE);
         } 
          bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
          strcpy(buffer,"该人已经被禁言\n");
          write_fd = write(sock_fd,buffer,BUFF_MAX);
       if (-1 == write_fd)
       {
  perror("write");
  exit(EXIT_FAILURE);
       }  
          bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
          scl_fd =  find_lin(&head,scl_name);
          strcpy(buffer,"你已经被禁言\n");
          write_fd = write(scl_fd,buffer,BUFF_MAX);
       if (-1 == write_fd)
       {
  perror("write");
  exit(EXIT_FAILURE);
       }  
    printf("scl out!\n");                       
    return;
}
///////////////////////////////////////////////////<chat_scl禁言>////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////<chat_rcl撤消禁言>//////////////////////////////////////////////////////////
void chat_rcl(int sock_fd,struct man * id)
{
        printf("rcl!\n");
        printf("state ->%d: ",RCL);
        ssize_t read_fd, write_fd;//存放读和写的描述符
        char rcl_name[20] = {0};
        int rcl_fd;
        char buffer[BUFF_MAX] = {0};//用于存放发送的信息
        read_fd = read(sock_fd,rcl_name, 20);//所禁言人的姓名 
        if (-1 == read_fd)
         {
  perror("read");
  exit(EXIT_FAILURE);
         } 
          bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
          strcpy(buffer,"该人已经解禁\n");
          write_fd = write(sock_fd,buffer,BUFF_MAX);
       if (-1 == write_fd)
       {
  perror("write");
  exit(EXIT_FAILURE);
       }  
          bzero(buffer, sizeof(buffer)); /* 清空缓冲区 */
          rcl_fd =  find_lin(&head,rcl_name);
          strcpy(buffer,"你已经被解禁\n");
          write_fd = write(rcl_fd,buffer,BUFF_MAX);
       if (-1 == write_fd)
       {
  perror("write");
  exit(EXIT_FAILURE);
       } 
    printf("rcl!\n");                  
    return;

}
///////////////////////////////////////////////////<chat_rcl撤消禁言>//////////////////////////////////////////////////////////
///////////////////////////////////////////////////<chat_esc退出>//////////////////////////////////////////////////////////////
void chat_esc(int sock_fd,struct man * id)
{
    printf("esc!\n");
    printf("state ->%d: ",ESC);
    printf("%s\n",(*id).name);
    struct sockfd_lis id_lin;
    printf("stacte %d : %s \n", ESC,(*id).name);//显示用户名
    printf("显示当前在现用户\n");
    delete_lin(&head,(*id).name);
    display_lin(&head);
    (*id).name[0] = '\0';//初始化该用户
    printf("esc out!\n");
    return;
}
///////////////////////////////////////////////////<chat_esc退出>//////////////////////////////////////////////////////////////
//////////////////////////////////////////////<o处理客户端信息的线程o>////////////////////////////////////////////////////
                        /*函数主线程部分*/
//主要进行接收客户端发过来的动作,并对动作进行相应的处理                     
void * serve_request(void* arg)
{
    printf("ask_serve\n");
    int sock_fd = (int)arg;//获得客户机的端口号
    ssize_t read_fd, write_fd;//读和写的描述符
    struct man id;//创建一个结构体用于存放客户端的客户信息
    memset((struct sockaddr_in*)&id, 0, sizeof(struct man));//初始化 
    int action[1];//用于存放客户端发来的动作
    action[0] = 0;//初始化动作
    pthread_t msg_id;//接收服务器线程的id
   
    int ret; 
    printf("serve request cline_id is %d\n", sock_fd);
   while(1)
    {
        printf("start action is %d.\n",action[0]);
         printf("start to read!\n");
     /////////////////////////////////////////
        read_fd = read(sock_fd, &action[0],1);
          if(-1 == read_fd)
     {
         perror("read");
    break;      
     }
     printf("read_fd is %d\n",read_fd);
     printf("action is %d.\n",action[0]);
     if(0 == action[0])
    {    action[0] =1;
          printf("please wait...\n");
      }
     printf("end action is %d.\n",action[0]);
          sleep(1);
     /*对相应的动作作判断*/ 
          if((LOG == action[0]))
     {
        printf("chat_log in\n");
         chat_log(sock_fd,&id);//登录部分
         action[0] = 1;//初始化动作
         printf("chat_log out\n");        
         continue;
     }
          if(REG == action[0])
     {
        printf("chat_reg in\n");    
         chat_reg(sock_fd,&id);//注册部分
         action[0] = 1; //初始化动作
         printf("chat_reg out\n");        
         continue;
     }
          if((PTO == action[0]))
     {
         printf("chat_pto in\n");    
         chat_pto(sock_fd,&id);//悄悄话部分
         action[0] = 1;//初始化动作
         printf("chat_pto out\n");        
         continue;
     }
          if((CTO == action[0]))
     {
         printf("chat_cto in\n");    
         chat_cto(sock_fd,&id);//公聊部分
         action[0] = 1;//初始化动作
         printf("chat_cto out\n");        
         continue;
     }
         if((VIM == action[0]))
     {
         printf("chat_vim in\n");    
         chat_vim(sock_fd,&id);//查看在线状态部分
         action[0] = 1;//初始化动作
         printf("chat_vim out\n");        
         continue;
     }
         if((VOM == action[0]))
     {
         printf("chat_vom in\n");    
         chat_vom(sock_fd,&id);//查看所有用户部分
         action[0] = 1;//初始化动作
         printf("chat_vom out\n");        
         continue;
     }
        if((KIC == action[0]))
     {
         printf("chat_klc in\n");      
         chat_kic(sock_fd,&id);//踢人部分
         action[0] = 1;//初始化动作
         printf("chat_kic out\n");          
         continue;
     }
       if((SCL == action[0]))
     {
         printf("chat_scl in\n");    
         chat_scl(sock_fd,&id);//禁言部分
         action[0] = 1;//初始化动作
         printf("chat_scl out\n");        
         continue;
     }
       if((RCL == action[0]))
     {
         printf("chat_rcl in\n");    
         chat_rcl(sock_fd,&id);//撤消禁言部分
         action[0] = 1;//初始化动作
         printf("chat_rcl out\n");        
         continue;
     }
        if((ESC == action[0]))
     {
         printf("chat_esc in\n");    
         chat_esc(sock_fd,&id);//登录部分
         action[0] = 1;//初始化动作
         printf("chat_esc out\n");        
         continue;
     }
         if(0 == action[0])
     {
         printf("please wait...");

     }

     printf("this is error0\n");
    
     break;
    }
    printf("this is error1\n");    
    return;
}
//////////////////////////////////////////////<o处理客户端信息的线程o>////////////////////////////////////////////////////
////////////////////////////////////////////////////////////<main>//////////////////////////////////////////////////////////////////
int main()
{
      int cilnsock_fd;//保存客户端sock地址
      int ret;//用于检测绑定.侦听.关闭的返回值
         
 struct sockaddr_in servaddr,clinaddr;//服务器和客户端地址的结构体
 socklen_t cli_addr_len;//用于存放地址结构体的长度
 
 /*创建一个套接口*/
    servsock_fd = socket(AF_INET,SOCK_STREAM, 0);
    if(-1 == servsock_fd)
    {   
        perror("socket");
        exit(EXIT_FAILURE);
    }
     /*初始化客户端地址*/
      memset((struct sockaddr_in*)&servaddr, 0, sizeof(struct sockaddr_in));
 servaddr.sin_family = AF_INET;//ipv4 
 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//服务器地址
 servaddr.sin_port = htons(PORT);//主机接口 
 int opt = 1;
 setsockopt(servsock_fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    /*绑定服务器地址与套接口*/
    ret = bind(servsock_fd, (struct sockaddr  *) &servaddr, (socklen_t)sizeof(servaddr));
    if(-1 == ret)
   {
        perror("bind");
   exit(EXIT_FAILURE);
   }
   /*监听*/
    ret = listen(servsock_fd,LISENT_BACK);
    if(-1 == ret)
  {
        perror("listen");
   exit(EXIT_FAILURE);
   }

   //creat_lin(&head);//创建线程链表头部
   while(1)
   {       
  cli_addr_len = sizeof(clinaddr);//用于存放地址结构体的长度
  printf("Waiting for client...\n");
  
  cilnsock_fd = accept(servsock_fd,  (struct   sockaddr *)&clinaddr, &cli_addr_len );//接收
  if(-1 == cilnsock_fd)
  {
   perror("accept");
   exit(EXIT_FAILURE);       
  }
  printf("state-> 0: Connection from IP %s\n", inet_ntoa(clinaddr.sin_addr));
  int err;//保存线程的返回值
  pthread_t tid;//保存线程的id
  tid = pthread_create(&tid, NULL, serve_request,(void *)cilnsock_fd);//创建一个新的线程分配给新登录的客户端
  if (0 != tid)
  {
   printf("Create thread fail:%s\n", strerror(err));
   exit(EXIT_FAILURE);
  }     
    }   
    exit(EXIT_SUCCESS);
}
/////////////////////////////////////////////////////<main>/////////////////////////////////////////////////////////////////////