(C语言)即时通讯系统

发布于:2022-12-28 ⋅ 阅读:(649) ⋅ 点赞:(0)

目录

1.基本功能以及使用注意事项

1.1基本介绍

2.服务器端

chatroom.c

2.1服务器初始化函数

2.2接受处理客户端请求连接

2.3线程函数

2.4线程函数内部处理客户端想执行的功能

2.5注册

2.6 数据库中插入函数

2.7创建在线用户链表

2.8 登录

2.9登录将用户插入链表

 2.10 登录在数据库验证账户与密码

2.11在数据库中查找用户是否存在

2.12 私聊功能

2.13判断用户是否在线

2.14 修改密码

2.15 进行群聊

2.16退出群聊 将链表节点删除

2.17 查看在线用户

2.19 注销用户

2.20保存聊天记录

2.21 重复登录判断

2.22查看聊天记录

2.23 文件传输

2.24管理员用户申请

2.25 在数据库中管理员表中查看是否存在该管理员

2.26//向管理员表中插入数据

2.28 管理员登录

2.29//在root表中查看该用户是否为管理员

2.30/判断管理员用户与密码是否正确

2.32管理员踢人

2.33管理员禁言

2.34解除禁言

2.35 //获取管理员头像

2.36创建表

2.37执行sql语句函数

2.38//根据名字修改密码

2.39指定删除普通用户的中数据

2.40指定删除管理员表中的数据

2.41撤销管理员身份

2.42判断链表是否为空

chatroom.h

2.客户端

client.c

client.h


1.基本功能以及使用注意事项

基本功能
1.注册 2.登录 3.群聊 4私聊 5.快捷短语 6.注销用户 7.修改密码


8.保存聊天记录  9.查看聊天记录  10.查看在线用户  11.文件传输


12.管理员申请  13.管理员踢人  14.管理员专属头像 15.禁言用户

16.解除禁言 17.撤销管理员身份    

1.1基本介绍

服务器采用tcp  多线程并发服务器

客户端采用两个线程 接受和发送线程    接受线程主要负责接受服务器发送过来的信号

写线程主要负责给服务器发送各种信号用于实现对应的功能,以及实现客户端与客户端之间的群聊或者私聊

注意事项:管理员不能踢出(禁言)管理员   只能对普通用户进行管理员操作

申请成为管理员必须先注册为普通用户

登录之前必须注册   不能重复登录(注册)

2.服务器端

chatroom.c

2.1服务器初始化函数

#include "chatroom.h"
int j; //用于线程号数组
int flag2 = 1;  //用于管理员禁言

//服务器初始化
void Init()  
{

    unsigned char ip_str[] = "192.168.91.151";

    unsigned char port_str[] = "8787";

    struct sockaddr_in serveraddr;
    socklen_t addrlen = sizeof(serveraddr);
    if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
    {
        ERRLOG("socket");
    }
    //第二部:填充网络信息结构体
    serveraddr.sin_addr.s_addr =  inet_addr(ip_str);
    serveraddr.sin_port =  htons(atoi(port_str));
    serveraddr.sin_family = AF_INET;
    int opt = 1;//设置端口复用
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    //第三步
    if((bind(sockfd,(struct sockaddr *)&serveraddr,addrlen)) == -1)
    {
        ERRLOG("bind");
    }

    //第四步
    if((listen(sockfd,100)) == -1)
    {
        ERRLOG("listen");
    }  
}

2.2接受处理客户端请求连接

//接受处理客户端
void server(online_userlist *head)
{   
    thread_node node;//结构体新增变量
    node.head = head;

    clientlist c_client;
    struct sockaddr_in clientaddr;
    while(1)
    {   
        socklen_t addrlen = sizeof(clientaddr);
        if((node.cfd = accept(sockfd,(struct sockaddr *)&clientaddr,&addrlen)) == -1)
        {
            ERRLOG("accept");
        }
        printf("客户端连接成功\n");
        if(pthread_create(&pti1[j],NULL,myfun,(void*)&node) != 0)
        {
            ERRLOG("pthread_create");
        }
        printf("服务线程测试\n");
        pthread_detach(pti1[j]);
        //为客户端进行服务
        j++;
    }
    close(sockfd);
}

2.3线程函数

void *myfun(void *arg)
{
    thread_node node;
    node = *((struct thread_node *)arg);
    
    while(1)
    {
        messagehand(&node);
    }
    close(node.cfd);
    return NULL;
}

2.4线程函数内部处理客户端想执行的功能

//线程函数内部处理客户端想执行的功能
void messagehand(thread_node *node)
{
    clientlist c_client;//创建一个和客户端一样的结构体
    
    int bytes = recv(node->cfd,&c_client,sizeof(c_client),0); //0阻塞接受
    if(c_client.flag == 3 || c_client.flag == 5)
    {
        insert_uprecord(node,&c_client);
    }
    if(bytes == -1)
    {
        ERRLOG("recv\n");
    }
    else if(bytes == 0)
    {
        exituser(node,&c_client);
        //printf("正在运行群聊函数\n");
        online_userlist *p = node->head;
        p=p->next;
        while(p!=NULL)//如果用p->next!=NULL  当p在最后一个结点是 p->next=NULL 无法进入循环
        {   
            if(p->c_fd != 0)
            {   
                char buf[50] = "\0";
                sprintf(buf,"[%s]:退出了",c_client.name);
                if(send(p->c_fd,buf,sizeof(buf),0) == -1)
                {
                    ERRLOG("send error");
                }
                memset(buf,0,sizeof(buf));
            }
            p=p->next;
        }
        printf("%s:退出了\n",c_client.name);
        pthread_exit(NULL);
    
    }
    printf("接受的结构体名字:%s  功能标志:%d  密码:%s  私聊对象:%s  管理员标志: %d\n",c_client.name,c_client.flag,c_client.password,c_client.to_name,c_client.root);
    
    switch(c_client.flag)
    {
        case 1:
            Register(node,&c_client);//注册用户
            printf("注册用户\n");        
        break;

        case 2:
            login(node,&c_client);//登录
            printf("用户登录功能\n");
        break;

        case 3:
            privatechat(node,&c_client); //私聊
            printf("私聊功能\n");
        break;

        case 4:
        changepassword(node,&c_client); //修改密码
        printf("修改密码\n");
        break;

        case 5:
        groupchat(node,&c_client);//进行群聊
        break;

        case 6:   //查看所有在线用户
        viewonline_user(node,&c_client);
        break;

        case 7://注销用户
        loguser(node,&c_client);
        break;

        case 8:
        Checkrecord(node);//查看聊天记录
        break;

        case 9:
        filetransfer(node,&c_client); //文件传输
        break;

        case 10:
        applyroot(node,&c_client); //申请管理员用户
        break;

        case 11:
        rootlogin(node,&c_client); //管理员登录
        break;

        case 12:
        rootkick(node,&c_client);  //管理员踢人
        break;

        case 13:
        silent(node,&c_client); //管理员禁言
        break;

        case 14:
        remsilent(node,&c_client); //管理员解除用户禁言
        break;

        case 15:
        cancelroot(node,&c_client); //取消管理员身份
        break;
    }


}

2.5注册

//注册
void Register(thread_node *node,clientlist *c)
{
    printf("判断:%s 是否在数据库\n",c->name);
    int ret = searchtable(c->name); //在数据库中查找是否已经注册过
    printf("%d",ret);
    if(1 == ret)
    {
        char arr[128] = {"账号已经存在,请重新注册"};
        if(send(node->cfd,arr,sizeof(arr),0) == -1)
        {
            ERRLOG("send error");
        }
        return;
    }
    else
    {
        insert_updata(node,c);  //向数据库中插入数据
    }
}

2.6 数据库中插入函数

//向数据库中插入
void insert_updata(thread_node *node,clientlist *c)
{   

    printf("注册的名字%s\n",c->name);
    char *errmsg;
    sqlite3 *db =NULL;
    char sql[200] = "\0";
    memset(sql,0,sizeof(sql));//清空sql
    sprintf(sql,"insert into user(name,password) values('%s','%s')",c->name,c->password);
    printf("数据库sql语句测试\n");
    execstate(sql);
    printf("\033[0;34m插入成功\033\n");
    char buf[100] = {"[系统日志]:注册成功...\n"};
    if(send(node->cfd,buf,sizeof(buf),0) == -1)
    {
        ERRLOG("send error");
    }
}

2.7创建在线用户链表

//在线用户链表
online_userlist* online_userlistcreate()
{
    online_userlist *head = (online_userlist *)malloc(sizeof(online_userlist));
    head->next = NULL;
    return head;
}

2.8 登录

void login(thread_node *node,clientlist *c)
{
    //判断是否注册
    if(0 == (searchtable(c->name)))
    {
        char buf[32] = "该用户不存在,请注册...";
        if(send(node->cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
        
    }
    else if( 0 == (veridandpassword(c)))//密码错误
    {

        char buf[20] = "密码输入错误..";
        if(send(node->cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
    }
    else if(1 == (veridandpassword(c)))//返回值为1账号密码正确
    {   
        if(1 ==Repeatlogin(node,c))//判断重复登录
        {
            online_insertion(node,c);
            char buf[32] = "登录成功..";
            if(send(node->cfd,buf,sizeof(buf),0) == -1)
            {
                ERRLOG("send error");
            }

            online_userlist *p = node->head;
            p=p->next;
            while(p!=NULL)//如果用p->next!=NULL  当p在最后一个结点是 p->next=NULL 无法进入循环
            {   
                if(p->c_fd != 0)
                {   
                    char buf[50] = "\0";
                    sprintf(buf,"[%s]:上线了",c->name);
                    if(send(p->c_fd,buf,sizeof(buf),0) == -1)
                    {
                        ERRLOG("send error");
                    }
                    memset(buf,0,sizeof(buf));
                }
                p=p->next;
            }
        }
        else
        {
            return;
        }
    }
}

2.9登录将用户插入链表

void online_insertion(thread_node *node,clientlist *c)
{
    online_userlist *tmp=(online_userlist *)malloc(sizeof(online_userlist));
    tmp->next=NULL;
    online_userlist *p =node->head;//定义一个指针为表头

    strcpy(tmp->name,c->name);
    tmp->c_fd = node->cfd;

    printf("判断:%s,%d是否进行插入链表\n",tmp->name,tmp->c_fd);
    if(1==onlineempty(p))
    {
        tmp->next=p->next;//令新插入的结点指针指向下一个结点
        p->next=tmp;
    }
    else
    {
        while(p->next!=NULL&&strncmp(p->next->name , tmp->name,1)<0)//当目的name小于源name
        {
            p=p->next;
        }
        //当p->next指向的数据大于或者等于需要插入的数据是跳出循环
        //此事p->next  向的是第一个大于value的值
        tmp->next=p->next;
        p->next=tmp;  //然后将其插入大于value的值之前
        putchar(10);
    }
    printf("链表插入完成\n");
}

 2.10 登录在数据库验证账户与密码

//验证账户与密码 正确返回1 错误返回0;
int veridandpassword(clientlist *p)
{   
    printf("已进入密码效验工作\n");
    int flag;
    sqlite3 *db = NULL;      //数据库的名字记得更换
    int ret = sqlite3_open("user.db",&db);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_open");
        exit(1);
    }
    printf("已打开数据库\n");
    char sql[200] = "\0";
    sprintf(sql,"select *from user;");
    char *errmsg;//定义指着指向错误信息
    char **result;//相当于二维数组  保存查询到的信息
    int nrow,ncolumn;//分别代表行和列
    ret = sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
    int j,i;
    int Index = ncolumn;
    int ret1,ret2;
    printf("已进行遍历数据库\n");
    for(i = 0 ; i < nrow+1;i++)
    {

        ret1 = (strcmp(result[i*ncolumn + 0],p->name));
        ret2 = (strcmp(result[i*ncolumn + 1],p->password));
        printf("正在进行账户密码效验\n");
        printf("账户:%s\n",result[i*ncolumn + 0]);
        printf("密码:%s\n",result[i*ncolumn + 1]);
        printf("密码:%s\n",p->password);
        if(0 == ret1 && 0 == ret2)
        {
                flag = 1;
                break;
        }//0行就是第一行  第i行第j列
    }
    if(flag == 1)
    {   printf("核对返回值为%d\n",flag);
        sqlite3_free_table(result);//释放数据库
        ret = sqlite3_close(db);
        if(SQLITE_OK != ret)
        {
            perror("sqlite3_close:");
            exit(1);
        }
        return flag;
    }
    else{
            flag = 0;
            sqlite3_free_table(result);//释放数据库
            ret = sqlite3_close(db);
            if(SQLITE_OK != ret)
            {
                perror("sqlite3_close:");
                exit(1);
            }
            return flag;
        }
}
    

2.11在数据库中查找用户是否存在

//在数据库查询用户 c存在返回1  不存在返回0
int searchtable(char *tablename)
{   

    int flag;
    sqlite3 *db = NULL;      
    int ret = sqlite3_open("user.db",&db);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_open");
        exit(1);
    }

    char sql[200] = "\0";
    sprintf(sql,"select *from user;");
    char *errmsg;//定义指着指向错误信息
    char **result;//相当于二维数组  保存查询到的信息
    int nrow,ncolumn;//分别代表行和列

    ret = sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
    int j,i;
    int Index = ncolumn;

    for(i = 1 ; i < nrow+1;i++)
    {
        int ret = strcmp(result[i*ncolumn + 0],tablename);
        if(ret == 0)
        {   
            flag = 1;
            
        }//0行就是第一行  第i行第j列
    }

    if(flag == 1)
    {   printf("数据库是否存在该用户%d存在\n",flag);

        sqlite3_free_table(result);//释放数据库
        ret = sqlite3_close(db);
        if(SQLITE_OK != ret)
        {
            perror("sqlite3_close:");
            exit(1);
        }
        return flag;
    }
    else
    {   
        flag = 0;
        printf("%d\n",flag);
        sqlite3_free_table(result);//释放数据库
        ret = sqlite3_close(db);
        if(SQLITE_OK != ret)
        {
            perror("sqlite3_close:");
            exit(1);
        }
        return flag;
    }
}

2.12 私聊功能

//私聊功能
void privatechat(thread_node *node,clientlist *c)
{   
    int flag = 0;
    printf("正在运行私聊函数\n");
    int to_cfd = Find_person(node,c);  //在线返回对方的文件描述符
    printf("私聊对象的文件描述符为%d\n",to_cfd);
    if(0 == to_cfd)
    {
        char buf[32] = "对方不在线...";
        if(send(node->cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
    }
    else
    {   
        if(0 == flag)
        {
            char buf1[128] = "\0";
            sprintf(buf1,"[系统日志]:正在与%s进行私聊",c->to_name);
            if(send(node->cfd,buf1,sizeof(buf1),0) == -1)
            {
                ERRLOG("send error");
            }
            flag++;
        }
        printf("正在进行消息:%s转发\n",c->msg);
        char buf[128] = "\0";
        sprintf(buf,"[%s悄悄对你说了一句]:%s",c->name,c->msg);
        if(send(to_cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
    }
    
}

2.13判断用户是否在线

//判断是否在线 在线返回对方文件描述符 不在线返回0
int Find_person(thread_node *node,clientlist *c)
{
    char s1[32]={0};
    strcpy(s1,c->to_name);//想跟s1进行私聊
    printf("正在判断%s是否在线\n",c->to_name);
    online_userlist *p = node->head;
    while(p!=NULL)
    {   
        if(strcmp(s1,p->name) == 0 ) 
        {   printf("%s在线\n",p->name);
            return p->c_fd;//私聊对象的文件描述符
        }
        p=p->next;
    }
    return 0;
}

2.14 修改密码

//修改密码
void changepassword(thread_node *node,clientlist *c)
{
    
    printf("用户%s将吧密码修改为%s",c->name,c->msg);
    Insert_updated_data(c->name,c->msg);
    char buf1[600] = "\0";

    sprintf(buf1,"[系统日志]:密码修改成功");
    if(send(node->cfd,buf1,sizeof(buf1),0) == -1)
    {
        ERRLOG("send error");
    }
    printf("用户%s已成功修改密码",c->name);
    exituser(node,c);
}

2.15 进行群聊

//功能标志5  进行群聊  
void groupchat(thread_node *node,clientlist *c)
{
    printf("正在运行管理员群聊函数\n");
    online_userlist *p = node->head;
    int ret;
    ret = onlineempty1(p);
    if(1 == ret)
    {
            char buf1[128] = "\0";
            strcpy(buf1,"[系统日志]:当前没有别的用户在线");
            if(send(node->cfd,buf1,sizeof(buf1),0) == -1)
            {
                ERRLOG("send error");
            }
        return;
    }
    printf("正在遍历链表给每个用户发送消息\n");
    printf("打印管路员标志%d\n",c->root);

    if(c->root == 1)
    {   
        getheadflag(c);//获取管理员头像
        printf("打印管理员头像%s\n",c->emojio);
        p=p->next;
        while(p!=NULL)//如果用p->next!=NULL  当p在最后一个结点是 p->next=NULL 无法进入循环
        {   
            if(p->c_fd != 0)
            {   printf("打印文件描述符%d \n",p->c_fd);
                char buf[128] = "\0";
                sprintf(buf,"%s[%s]:%s",c->emojio,c->name,c->msg);
                if(send(p->c_fd,buf,sizeof(buf),0) == -1)
                {
                    ERRLOG("send error");
                }
                memset(buf,0,sizeof(buf));
            }
            p=p->next;
        }
    }
    else
    {
        p=p->next;
        while(p!=NULL)//如果用p->next!=NULL  当p在最后一个结点是 p->next=NULL 无法进入循环
        {   
            if(p->c_fd != 0)
            {   printf("打印文件描述符%d \n",p->c_fd);
                char buf[100] = "\0";
                sprintf(buf,"[%s]:%s",c->name,c->msg);
                if(send(p->c_fd,buf,sizeof(buf),0) == -1)
                {
                    ERRLOG("send error");
                }
                memset(buf,0,sizeof(buf));
            }
            p=p->next;
        }
    }
}

2.16退出群聊 将链表节点删除

//退出群聊 删除链表内的用户结点
void exituser(thread_node *node,clientlist *c)
{
    online_userlist *p = node->head;
    online_userlist *q;
    while(p->next!=NULL)
    {
        if(strcmp(c->name,p->next->name)==0)
        {
            q=p->next;
            p->next=p->next->next;
            free(q);
            q=NULL;
            printf("将%s踢出链表成功\n",c->name);
            return;
        }
        p=p->next;
    }
}

2.17 查看在线用户

//查看所有在线用户
void viewonline_user(thread_node *node,clientlist *c)
{

    online_userlist *p = node->head->next;
    int ret;
    ret = onlineempty(p);
    if(1 == ret)
    {
            char buf1[128] = "\0";
            strcpy(buf1,"[系统日志]:当前没有别的用户在线");
            if(send(node->cfd,buf1,sizeof(buf1),0) == -1)
            {
                ERRLOG("send error");
            }
        return;
    }

    while(p!=NULL)//如果用p->next!=NULL  当p在最后一个结点是 p->next=NULL 无法进入循环
    {   
        if(p->c_fd != 0)
        {   
            char buf[70] = {0};
            memset(buf,0,sizeof(buf));
            printf("%s当前在线3\n",p->name);
            sprintf(buf,"[%s]:当前在线",p->name);
            if(send(node->cfd,buf,sizeof(buf),0) == -1)
            {
                ERRLOG("send error");
            }
            sleep(1);
        }
        p=p->next;
    }
}

2.19 注销用户

//注销用户
void loguser(thread_node *node,clientlist *c)
{
    deleteuser(c);
    if(c->root == 1)
    {
        deleteroot(c);
    }
    printf("注销用户删除数据库成功\n");
    char buf[32] = "注销成功..";
    if(send(node->cfd,buf,sizeof(buf),0) == -1)
    {
        ERRLOG("send error");
    }
    exituser(node,c);
    printf("注销用户删除链表结点成功\n");
}

2.20保存聊天记录

//将聊天记录插入记录表(保存聊天记录)
void insert_uprecord(thread_node *node,clientlist *c)
{   
    printf("正在进行聊天记录存储\n");
    printf("聊天方式标志位:%d",c->flag);
    printf("聊天内容:%s",c->msg);
    time_t timep;
    struct tm *p;
    time (&timep);
    p=gmtime(&timep);
    char newtime[32] = {0};
    sprintf(newtime,"%d-%d-%d:%d:%d\n",1+p->tm_mon,p->tm_mday,8+p->tm_hour,p->tm_min,p->tm_sec);
    printf("获取时间%s\n",newtime);
    int cc=1;
    char *errmsg;
    sqlite3 *db =NULL;
    char sql[200] = "\0";
    memset(sql,0,sizeof(sql));//清空sql

    pthread_mutex_lock(&mutex);
    sprintf(sql,"insert into record(time,name,record) values('%s','%s','%s')",newtime,c->name,c->msg);
    printf("数据库sql语句测试\n");
    execstate(sql);
    pthread_mutex_unlock(&mutex);
    printf("\033[0;34m聊天记录保存成功\033\n");


}

2.21 重复登录判断

//重复登录判断
int Repeatlogin(thread_node *node,clientlist *c)
{   
    printf("正在判断是否重复登录\n");
    char s1[32]={0};
    strcpy(s1,c->name);//判断自己是否登录
    printf("正在判断%s是否在线\n",c->to_name);
    online_userlist *p = node->head;
    while(p!=NULL)
    {   
        if(strcmp(s1,p->name) == 0 ) 
        {   printf("%s在线,重复登录\n",p->name);
            char buf[32] = "您已在线,请勿重复登录";
            if(send(node->cfd,buf,sizeof(buf),0) == -1)
            {
                ERRLOG("send error");
            }
            return 0;
        }
        p=p->next;
    }
    printf("未遍历到该用户,可以进行登录\n");
    return 1;
}

2.22查看聊天记录

//查看聊天记录
void Checkrecord(thread_node *node)
{
    printf("已进入聊天记录返回客户端工作\n");
    int flag;
    sqlite3 *db = NULL;      
    int ret = sqlite3_open("user.db",&db);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_open");
        exit(1);
    }
    printf("已打开数据库\n");
    char sql[200] = "\0";
    sprintf(sql,"select *from record;");
    char *errmsg;//定义指着指向错误信息
    char **result;//相当于二维数组  保存查询到的信息
    int nrow,ncolumn;//分别代表行和列
    ret = sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
    int j,i;
    int Index = ncolumn;
    int ret1,ret2;
    printf("已进行遍历数据库\n");
    char buf[256] = {0};
    for(i = 1 ; i < nrow+1;i++)
    {
        printf("正在将聊天记录发送给客户端\n");
        sprintf(buf,"%s\n[%s]:%s",result[i*ncolumn + 0],result[i*ncolumn + 1],result[i*ncolumn + 2]);
        printf("时间:%s\n",result[i*ncolumn + 0]);
        printf("用户:%s\n",result[i*ncolumn + 1]);
        printf("消息内容:%s\n",result[i*ncolumn + 2]);
        printf("%s",buf);
        if(send(node->cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
    }
}

2.23 文件传输

//文件传输
void filetransfer(thread_node *node,clientlist *c)
{
    MSG msg;
    printf("正在运行文件传输函数\n");
    int to_cfd = Find_person(node,c);  //在线返回对方的文件描述符
    printf("私聊对象的文件描述符为%d\n",to_cfd);

    char buf[256] = "\0";
    printf("***********11111\n");
    printf("%s",c->buf);
    printf("***********22222\n");

    strcpy(msg.text,c->buf);
    msg.num = c->num;
    if(0 == to_cfd)
    {
        char buf1[32] = "对方不在线...";
        if(send(node->cfd,buf1,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
    }
    else
    {   
        while(flag2)
        {   
            printf("正在向对方发送文件传输信号\n");
            if(send(to_cfd,"文件存在进行文件传输",N,0) == -1)
            {
                ERRLOG("send error");
            }
            flag2 = 0;
        }
        if(strcmp(buf,"0") == 0)
        {   
            printf("文件内容全部发送完成\n");
            flag2 = 1;
        }
        sleep(1);
        printf("本次向对方送的内容%s\n",msg.text);
        if(send(to_cfd,&msg,sizeof(msg),0) == -1)
        {
            ERRLOG("send error");
        }
        printf("单次发送内容完成\n");
        memset(&msg,0,sizeof(msg));
    }

2.24管理员用户申请

//管理员用户的申请
void applyroot(thread_node *node,clientlist *c)
{
    printf("正在判断:%s 是否已经是管理员\n",c->name);
    int ret = searchtableroot(c->name);
    printf("%d",ret);
    if(1 == ret)
    {
        char arr[128] = {"您已是管理员.."};
        if(send(node->cfd,arr,sizeof(arr),0) == -1)
        {
            ERRLOG("send error");
        }
        return;
    }
    else
    {
        insert_updataroot(node,c);
    }
}

2.25 在数据库中管理员表中查看是否存在该管理员

//在数据库中管理员表中查看是否存在该管理员
int searchtableroot(char *tablename)
{   

    int flag;
    sqlite3 *db = NULL;      
    int ret = sqlite3_open("user.db",&db);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_open");
        exit(1);
    }

    char sql[200] = "\0";
    sprintf(sql,"select *from root;");
    char *errmsg;//定义指着指向错误信息
    char **result;//相当于二维数组  保存查询到的信息
    int nrow,ncolumn;//分别代表行和列

    ret = sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
    int j,i;
    int Index = ncolumn;

    for(i = 1 ; i < nrow+1;i++)
    {
        int ret = strcmp(result[i*ncolumn + 1],tablename);
        if(ret == 0)
        {   
            flag = 1;
            
        }//0行就是第一行  第i行第j列
    }

    if(flag == 1)
    {   printf("root表中该用户%d存在\n",flag);

        sqlite3_free_table(result);//释放数据库
        ret = sqlite3_close(db);
        if(SQLITE_OK != ret)
        {
            perror("sqlite3_close:");
            exit(1);
        }
        return flag;
    }
    else
    {   
        printf("root表中该用户%d不存在\n",flag);
        flag = 0;
        printf("%d\n",flag);
        sqlite3_free_table(result);//释放数据库
        ret = sqlite3_close(db);
        if(SQLITE_OK != ret)
        {
            perror("sqlite3_close:");
            exit(1);
        }
        return flag;
    }
}

2.26//向管理员表中插入数据

//向root表中插入数据
void insert_updataroot(thread_node *node,clientlist *c)
{
        printf("申请管理员的用户%s\n",c->name);
    char *errmsg;
    sqlite3 *db =NULL;
    char sql[200] = "\0";
    memset(sql,0,sizeof(sql));//清空sql

    pthread_mutex_lock(&mutex);
    sprintf(sql,"insert into root(head,name,password) values('%s','%s','%s');",c->emojio,c->name,c->password);
    printf("将 头像:%s,名字;%s,密码:%s 插入表中\n",c->emojio,c->name,c->password);
    execstate(sql);
    pthread_mutex_unlock(&mutex);


    printf("\033[0;34m插入成功\033\n");
    char buf[100] = {"管理员申请成功"};
    if(send(node->cfd,buf,sizeof(buf),0) == -1)
    {
        ERRLOG("send error");
    }
    exituser(node,c);//注册完将其踢出链表让其进入初始界面从新登录
    return;
}

2.28 管理员登录

//管理员登录
void rootlogin(thread_node *node,clientlist *c)
{
    if(0 == (rootsearch(c->name)))
    {
        char buf[32] = "该用户非管理员";
        if(send(node->cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
        
    }
    else if( 0 == (rootveridandpassword(c)))//密码错误
    {
        char buf[20] = "密码输入错误";
        if(send(node->cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
    }
    else if(1 == (rootveridandpassword(c)))//返回值为1账号密码正确
    {  
        if(rootRepeatlogin(node,c))
        {
            online_insertion(node,c);
            char buf[32] = "管理员登录成功..";
            if(send(node->cfd,buf,sizeof(buf),0) == -1)
            {
                ERRLOG("send error");
            }
            online_userlist *p = node->head;
            p=p->next;
            while(p!=NULL)//如果用p->next!=NULL  当p在最后一个结点是 p->next=NULL 无法进入循环
            {   
                if(p->c_fd != 0)
                {   
                    char buf[70] = "\0";
                    sprintf(buf,"%s[%s]:上线了",c->emojio,c->name);
                    if(send(p->c_fd,buf,sizeof(buf),0) == -1)
                    {
                        ERRLOG("send error");
                    }
                    memset(buf,0,sizeof(buf));
                }
                p=p->next;
            }
        }
        else
        {
            return;
        }
    }
}

2.29//在root表中查看该用户是否为管理员

//在root表中查看该用户是否为管理员
int rootsearch(char *tablename)
{   

    int flag;
    sqlite3 *db = NULL;      
    int ret = sqlite3_open("user.db",&db);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_open");
        exit(1);
    }

    char sql[200] = "\0";
    sprintf(sql,"select *from root;");
    char *errmsg;//定义指着指向错误信息
    char **result;//相当于二维数组  保存查询到的信息
    int nrow,ncolumn;//分别代表行和列

    ret = sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
    int j,i;
    int Index = ncolumn;

    for(i = 1 ; i < nrow+1;i++)
    {
        int ret = strcmp(result[i*ncolumn + 1],tablename);
        if(ret == 0)
        {   
            flag = 1;
        }//0行就是第一行  第i行第j列
    }

    if(flag == 1)
    {   printf("数据库是否存在该用户%d存在\n",flag);

        sqlite3_free_table(result);//释放数据库
        ret = sqlite3_close(db);
        if(SQLITE_OK != ret)
        {
            perror("sqlite3_close:");
            exit(1);
        }
        return flag;
    }
    else
    {   
        flag = 0;
        printf("%d\n",flag);
        sqlite3_free_table(result);//释放数据库
        ret = sqlite3_close(db);
        if(SQLITE_OK != ret)
        {
            perror("sqlite3_close:");
            exit(1);
        }
        return flag;
    }
}

2.30/判断管理员用户与密码是否正确

//判断管理员用户与密码
int rootveridandpassword(clientlist *c)
{   
    printf("已进入管理员的密码效验工作\n");
    int flag;
    sqlite3 *db = NULL;      //数据库的名字记得更换
    int ret = sqlite3_open("user.db",&db);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_open");
        exit(1);
    }
    printf("已打开数据库\n");
    char sql[200] = "\0";
    sprintf(sql,"select *from root;");
    char *errmsg;//定义指着指向错误信息
    char **result;//相当于二维数组  保存查询到的信息
    int nrow,ncolumn;//分别代表行和列
    ret = sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
    int j,i;
    int Index = ncolumn;
    int ret1,ret2;
    printf("已进行遍历数据库\n");
    for(i = 0 ; i < nrow+1;i++)
    {
        ret1 = (strcmp(result[i*ncolumn + 1],c->name));
        ret2 = (strcmp(result[i*ncolumn + 2],c->password));
        printf("正在进行账户密码效验\n");
        
        printf("账户:%s\n",result[i*ncolumn + 1]);
        printf("密码:%s\n",result[i*ncolumn + 2]);
        printf("密码:%s\n",c->password);
        if(0 == ret1 && 0 == ret2)
        {
                strcpy(c->emojio,result[i*ncolumn + 0]);
                printf("打印管理员存在数据库中的头像%s",result[i*ncolumn + 0]);
                printf("打印被赋值后的当前结构体头像%s",c->emojio);
                flag = 1;
                break;
        }//0行就是第一行  第i行第j列
    }
    if(flag == 1)
    {   printf("核对返回值为%d\n",flag);
        sqlite3_free_table(result);//释放数据库
        ret = sqlite3_close(db);
        if(SQLITE_OK != ret)
        {
            perror("sqlite3_close:");
            exit(1);
        }
        return flag;
    }
    else{
            flag = 0;
            sqlite3_free_table(result);//释放数据库
            ret = sqlite3_close(db);
            if(SQLITE_OK != ret)
            {
                perror("sqlite3_close:");
                exit(1);
            }
            return flag;
        }
}

2.31//管理员重复登录判断

//管理员重复登录判断
int rootRepeatlogin(thread_node *node,clientlist *c)
{   
    printf("正在判断是否重复登录\n");
    char s1[32]={0};
    strcpy(s1,c->name);//判断自己是否登录
    printf("正在判断%s是否在线\n",c->to_name);
    online_userlist *p = node->head;
    while(p!=NULL)
    {   
        if(strcmp(s1,p->name) == 0 ) 
        {   printf("%s在线,重复登录\n",p->name);
            char buf[32] = "您已在线,请勿重复登录";
            if(send(node->cfd,buf,sizeof(buf),0) == -1)
            {
                ERRLOG("send error");
            }
            return 0;
        }
        p=p->next;
    }
    printf("未遍历到该用户,可以进行登录\n");
    return 1;
}

2.32管理员踢人

//管理员踢人
void rootkick(thread_node *node,clientlist *c)
{
    int to_cfd = Find_person(node,c);  //在线返回对方的文件描述符
    printf("踢出对象的文件描述符为%d\n",to_cfd);
    if(0 == to_cfd)
    {
        char buf[32] = "对方不在线...";
        if(send(node->cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
    }
    else
    {   
        if(searchtableroot(c->to_name) == 1)
        {
            char buf[128] = "对方是管理员,无法进行操作";
            if(send(node->cfd,buf,sizeof(buf),0) == -1)
            {
                ERRLOG("send error");
            }
            return;
        }
        else
        {
            char buf[128] = "管理员已将你踢出聊天室";
            if(send(to_cfd,buf,sizeof(buf),0) == -1)
            {
                ERRLOG("send error");
            }
        }
    }
}

2.33管理员禁言

//管理员禁言
void silent(thread_node *node,clientlist *c)
{
    int to_cfd = Find_person(node,c);  //在线返回对方的文件描述符
    printf("禁言对象的文件描述符为%d\n",to_cfd);
    if(0 == to_cfd)
    {
        char buf[32] = "对方不在线...";
        if(send(node->cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
    }
    else
    {
        if(searchtableroot(c->to_name) == 1)
        {
            char buf[128] = "对方是管理员,无法进行操作";
            if(send(node->cfd,buf,sizeof(buf),0) == -1)
            {
                ERRLOG("send error");
            }
            return;
        }
        else
        {
            char buf[128] = "管理员已将你禁言";
            if(send(to_cfd,buf,sizeof(buf),0) == -1)
            {
                ERRLOG("send error");
            }
        }
    }
}

2.34解除禁言

//管理员解除禁言
void remsilent(thread_node *node,clientlist *c)
{
    int to_cfd = Find_person(node,c);  //在线返回对方的文件描述符
    printf("解除禁言对象的文件描述符为%d\n",to_cfd);
    if(0 == to_cfd)
    {
        char buf[32] = "对方不在线...";
        if(send(node->cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
    }
    else
    {
        char buf[128] = "管理员已将你解除禁言";
        if(send(to_cfd,buf,sizeof(buf),0) == -1)
        {
            ERRLOG("send error");
        }
    }
}

2.35 //获取管理员头像

//获取管理员头像
void getheadflag(clientlist *c)
{
    int flag;
    sqlite3 *db = NULL;      
    int ret = sqlite3_open("user.db",&db);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_open");
        exit(1);
    }

    char sql[200] = "\0";
    sprintf(sql,"select *from root;");
    char *errmsg;//定义指着指向错误信息
    char **result;//相当于二维数组  保存查询到的信息
    int nrow,ncolumn;//分别代表行和列

    ret = sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
    int j,i;
    int Index = ncolumn;

    for(i = 1 ; i < nrow+1;i++)
    {
        int ret = strcmp(result[i*ncolumn + 1],c->name);
        if(ret == 0)
        {   strcpy(c->emojio,result[i*ncolumn + 0]);
            flag = 1;
            printf("当前管理员头像%s\n",result[i*ncolumn + 0]);
            printf("c->emojio=%s\n",c->emojio);
        }//0行就是第一行  第i行第j列
    }

    if(flag == 1)
    {   printf("管理员头像获取成功%s存在\n",c->emojio);

        sqlite3_free_table(result);//释放数据库
        ret = sqlite3_close(db);
        if(SQLITE_OK != ret)
        {
            perror("sqlite3_close:");
            exit(1);
        }
        return;
    }
    else
    {   
        printf("管理员头像获取失败%d不存在\n",flag);
        flag = 0;
        printf("%d\n",flag);
        sqlite3_free_table(result);//释放数据库
        ret = sqlite3_close(db);
        if(SQLITE_OK != ret)
        {
            perror("sqlite3_close:");
            exit(1);
        }
        return;
    }
}

2.36创建表

//创建表  注意更换数据库
void createtable()
{
    sqlite3 *db = NULL;  //目标数据库
    int ret = sqlite3_open("user.db",&db);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_open");
        exit(1);
    }
    char *errmsg;
    char sql[500] = "\0";
    strcpy(sql,"create table user (name text,password text);");
    ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_exec:");
        printf("errmsg:%s\n",errmsg);
        exit(1);
    }
    ret = sqlite3_close(db);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_close:");
        exit(1);
    }
    return;
}

2.37执行sql语句函数

//执行sql语句函数
void execstate(char *sql)//执行SQL语句
{
    sqlite3 *db =NULL;
    int ret = sqlite3_open("user.db",&db);
    if(SQLITE_OK != ret)
    {
        ERRLOG("sqlite3_open");
    }
    char *errmsg;
    ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
    if(SQLITE_OK != ret)
    {
        ERRLOG("sqlite3_exec");
    }
    ret = sqlite3_close(db);
    if(SQLITE_OK != ret)
    {
        perror("sqlite_close:");
        exit(1);
    }
}

2.38//根据名字修改密码

//根据名字修改密码
void Insert_updated_data(char *name,char *password)
{
    char sql[500] = "\0";
    sprintf(sql,"update user set password = '%s' where name = '%s';",password,name);
    execstate(sql);
    
}

2.39指定删除普通用户的中数据

//指定删除数据库里面的用户
void deleteuser(clientlist *c)
{   

    char sql[200] = "\0";
    memset(sql,0,sizeof(sql));//清空sql
    sprintf(sql,"delete from user where name = '%s';",c->name);
    execstate(sql);
    printf("删除数据库内容成功\n");
}

2.40指定删除管理员表中的数据

//指定删除数据库里面的用户
void deleteroot(clientlist *c)
{   

    char sql[200] = "\0";
    memset(sql,0,sizeof(sql));//清空sql
    sprintf(sql,"delete from root where name = '%s';",c->name);
    execstate(sql);
    printf("删除root内容成功\n");
}

2.41撤销管理员身份

//功能标志15 撤销管理员身份
void cancelroot(thread_node *node,clientlist *c)// 功能标志15 撤销管理员身份
{
    char buf[128] = "撤销成功";
    if(send(node->cfd,buf,sizeof(buf),0) == -1)
    {
        ERRLOG("send error");
    }
    deleteroot(c);
    exituser(node,c);
    return;
}

2.42判断链表是否为空

//判断链表是否为空
int onlineempty(online_userlist *head)
{
    if (head->next==NULL)
    {
        return  1 ;
    }
    else 
    {
        return 0;
    }
}
//判断除自己是否还有别人在线
int onlineempty1(online_userlist *head)
{
    if (head->next->next==NULL)
    {
        return  1 ;
    }
    else 
    {
        return 0;
    }
}

chatroom.h

#ifndef _CHATROOM_H
#define _CAHTROOM_H
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <sqlite3.h>
#include <time.h>
#define N 256
#define ERRLOG(errmsg) do{\
                        perror(errmsg);\
                        printf("%s - %s - %d\n",__FILE__,__func__,__LINE__);\
                        exit(1);\
                }while(0)

#define MAXLINE 8192
pthread_mutex_t mutex;
typedef struct client
{
        int flag; //功能标志 注册标志1 登录2  私聊3 修改密码4 群聊界面5 查看在线用户6 注销用户7  查看聊天记录8  下载文件9
        char emojio[20];//头像保存
        char name[32];//姓名
        int  root;    //管理员标志
        char msg[50];//聊天内容
        char password[32];//密码
        char to_name[50];//聊天对象
        char buf[256];//文件内容 
        int num;      
}clientlist;

typedef struct file
{
        char text[N];
        int num;
}MSG;

typedef struct online_user
{
        char name[32];//姓名
        int c_fd;
        struct  online_user*next;  //指针域
}online_userlist;

typedef struct thread_node
{
        int cfd;
        online_userlist *head;
}thread_node;

//在线用户链表
online_userlist* online_userlistcreate();

int sockfd; 

pthread_t pti1[500];//线程号数组用于保存accept线程号

void Init();//初始化 创建套接字等

void server();//accept接受创建线程

void *myfun(void *arg);//进入线程函数

void messagehand(thread_node *node);//接受消息 判断功能标志位

void insert_updata(thread_node *node,clientlist *c);//向数据库中插入

int searchtable(char *tablename);//在数据库查询用户 存在返回1 不存在返回0

void execstate(char *sql);//执行sql语句

int veridandpassword(clientlist *p);//判断账户密码是否正确 正确返回1错误返回0

void Register(thread_node *node,clientlist *c); //注册 判断是否已经存在 不存在进行插入数据库

int onlineempty(online_userlist *head);//判断链表是否为空

void login(thread_node *node,clientlist *c);//用户登录
//将登录用户添加至链表
void online_insertion(thread_node *node,clientlist *c);//登录用户插入链表

int Find_person(thread_node *node,clientlist *c);判断是否在线 在线返回对方文件描述符

void privatechat(thread_node *node,clientlist *c);//私聊

void changepassword(thread_node *node,clientlist *c);

void Insert_updated_data(char *name,char *password);//在数据库中按照名字修改密码

void groupchat(thread_node *node,clientlist *c);//进行群聊

int onlineempty1(online_userlist *head);//判断除了自己之外是否还要有别人在线

void exituser(thread_node *node,clientlist *c);//将退出聊天室的用户删除结点

void viewonline_user(thread_node *node,clientlist *c);//功能 标志查看所有在线用户

void deleteuser(clientlist *c);//指定删除数据库内用

void loguser(thread_node *node,clientlist *c);//注销用户

void insert_uprecord(thread_node *node,clientlist *c);//将聊天记录保存至数据库

int Repeatlogin(thread_node *node,clientlist *c);//判断是否重复登录

void Checkrecord(thread_node *node);//查看聊天记录

void filetransfer(thread_node *node,clientlist *c);//文件传输

void applyroot(thread_node *node,clientlist *c);//申请管理员用户

int searchtableroot(char *tablename);//判断该用户是否是已经是管理员

void insert_updataroot(thread_node *node,clientlist *c);//向管理员表中插入管理员资料

void rootlogin(thread_node *node,clientlist *c);//管理员登录

int rootsearch(char *tablename);//在root表中查看该用户是否为管理员

int rootveridandpassword(clientlist *p);//判断管理员密码

void rootkick(thread_node *node,clientlist *c);//管理员踢人

void silent(thread_node *node,clientlist *c);//管理员禁言

void remsilent(thread_node *node,clientlist *c);//管理员解除禁言

void getheadflag(clientlist *c);//获取管理员头像

int rootRepeatlogin(thread_node *node,clientlist *c);//管理员重复登录

void deleteroot(clientlist *c);//指定删除root表中的用户

void cancelroot(thread_node *node,clientlist *c);//取消管理员身份


#endif

2.客户端

client.c

#include "clientaddr.h"
unsigned char ip_str[] = "192.168.91.151";

unsigned char port_str[] = "8787";
int flag1 = 0;
int flag2 = 1;

void n_init()//客户端初始化框架
{
    clientfd2  = socket(AF_INET,SOCK_STREAM,0);
    if(clientfd2 == -1)
    {
        perror("socket");
        return;
    }
    struct sockaddr_in clientaddr;
    clientaddr.sin_family = AF_INET;//协议族  IPV4
    clientaddr.sin_addr.s_addr = inet_addr(ip_str); 
    /*in_addr_t inet_addr(const char *cp);将点分十进制字符串ip地址转化为网络序的无符号4字节
    整数ip地址*/
    int addrlen = sizeof(clientaddr);
    clientaddr.sin_port = htons(atoi(port_str));
    if(connect(clientfd2,(struct sockaddr *)&clientaddr,addrlen)==-1)
    {
        perror("\033[0;31m无法连接到服务器\033[0m\n");
        ERRLOG("connect");
    }
    return;
}

void selectfun()//进入页面选着功能
{       
        usleep(500*1000);
        system("clear");
        printf("\033[0;46m*===================================================================*\033[0m\n");
        printf("\033[0;46m|                                                                   |\033[0m\n");
        printf("\033[0;46m|*********************\033[0;33m欢迎来到防脱发研究中心\033[0;46m************************|\033[0m\n");
        printf("\033[0;46m|                                                      作者:爱码士  |\033[0m\n");
        printf("\033[0;46m|-------------------------------------------------------------------|\033[0m\n");
        printf("\033[0;46m|                                                                   |\033[0m\n");
        printf("\033[0;46m|                         \033[0;35m1.用户登录💩\033[0;46m                              |\033[0m\n");
        printf("\033[0;46m|                                                                   |\033[0m\n");
        printf("\033[0;46m|                         \033[0;32m2.帐号注册👾\033[0;46m                              |\033[0m\n");
        printf("\033[0;46m|                                                                   |\033[0m\n");
        printf("\033[0;46m|                         \033[0;33m3.管理员登录🐯\033[0;46m                            |\033[0m\n");
        printf("\033[0;46m|                                                                   |\033[0m\n");
        printf("\033[0;46m|                         \033[0;31m 0:退出聊天室🐴\033[0;46m                           |\033[0m\n");
        printf("\033[0;46m|                                                                   |\033[0m\n");
        printf("\033[0;46m*===================================================================*\033[0m\n");
        printf("\n"); 
        int num;
        scanf("%d",&num);
        getchar();
        switch (num)
        {             
            case 0:
            exit_room();//退出聊天室
            break;

            case 1:
            system("clear");
            printf("\033[0;31m正在进行用户登录..\033[0m\n");
            system("./zjn");
            user_login();//登录
            break;

            case 2:
                system("clear");
                printf("\033[0;31m正在进行账号注册\033[0m\n");
                user_register();//返回注册页面
                selectfun();
            break;

            case 3:
                system("clear");
                printf("\033[0;31m正在进行管理员登录\033[0m\n");
                rootlogin();
                putchar(10);
            break;

            case 4:
                system("clear");
                printf("\033[0;31m正在退出聊天室\033[0m\n");
                exit_room();
                putchar(10);
            break;
            default:
                system("clear");
                printf("\033[0;31m对不起输入错误请从新输入..\033[0m\n");
                selectfun();
            return;
        }
}

void funcinto()//第二阶段选择进入
{
    system("clear");
    printf("\033[34m                                         \033[0;36m<1:私聊功能>🐱\033[0;34m            \033[0m\n");
    putchar(10);
    printf("\033[34m                               \033[0;36m🐒<2:进入群聊>\033[0;34m           \033[0m\n");
    putchar(10);
    printf("\033[34m                                         \033[0;36m<3:修改密码>🐶\033[0;34m       \033[0m\n");
    putchar(10);
    printf("\033[0;31m                              \033[0;36m🐩<4:查看当前在看用户>\033[0;34m           \033[0m\n");
    putchar(10);
    printf("\033[34m                                         \033[0;31m<5:注销用户>🦒\033[0;34m    \033[0m\n");
    putchar(10);
    printf("\033[33m                              \033[0;33m🐴<6:申请称为管理员>\033[0;34m    \033[0m\n");
    putchar(10);
    printf("\033[34m                                         \033[0;33m🐆<0:退出聊天室>\033[0;34m    \033[0m\n");
    int num;
    scanf("%d",&num);
    getchar();
    switch (num)
    {               
        case 0:
        printf("\033[0;31m正在退出聊天室..\033[0m\n");
        exit_room(); 
        putchar(10);
        break;

        case 1:
        system("clear");
        printf("\033[0;31m正在进入私聊功能..\033[0m\n");
        privatechat();
        funcinto();
        break;
        case 2:
            system("clear");
            printf("\033[0;31m正在入群聊功能\033[0m\n");
            groupchat();
            funcinto();
            break;
        case 3:
            system("clear");
            printf("\033[0;31m正在进行修改密码\033[0m\n");
            changpassword();
            selectfun();
            putchar(10);
            break;
        case 4:
        
            system("clear");
            printf("\033[0;31m正在查看在线用户\033[0m\n");
            viewonline_user();
            sleep(3);
            funcinto();
            break;
        case 5:
            system("clear");
            printf("\033[0;31m正在进行注销用户\033[0m\n");
            deleteuser();
            sleep(1);
            selectfun();
            putchar(10);
            break;
        case 6:
            system("clear");
            printf("\033[0;31m正在申请成为管理员\033[0m\n");
            applyroot();
            putchar(10);
        break;
        default:
            system("clear");
            printf("\033[0;31m对不起输入错误请从新输入..\033[0m\n");
            funcinto();
            return;
    }
}

void user_register()//功能标志1 用户注册
{
    ssize_t  ret;
    char password[50];
    system("clear");
    printf("\033[0;31m请输入你的名字..\033[0m\n");
    scanf("%s",ts.name);
    system("clear");
    printf("\033[0;31m请输入你的密码\033[0m\n");
    system("stty -echo");
    scanf("%s",password);
    system("stty echo");
    system("clear");
    printf("\033[0;31m请再次确认你的密码\033[0m\n");
    system("stty -echo");
    scanf("%s",ts.password);
    system("stty echo");

    
    if(strcmp(password,ts.password) == 0)
    {
        system("./zjn");
        ts.flag = 1;
        ret =send(clientfd2,&ts,sizeof(clientlist),0);
        if(ret == -1)
        {
            ERRLOG("send");
        }
        return; 
    }
    else
    {
        printf("\033[0;31m输入密码不一致请从新输入...\033[0m\n");
        sleep(1);
        user_register(ts);
    }
    
}

void user_login()//功能标志 2用户登录
{
    
    ssize_t  ret;
    system("clear");
    printf("\033[0;31m请输入你的名字..\033[0m\n");
    scanf("%s",ts.name);
    system("clear");
    printf("\033[0;31m请输入你的密码\033[0m\n");
    system("stty -echo");
    scanf("%s",ts.password);

    sleep(1);
    system("stty echo");
    ts.flag = 2;  //用户登录标志位
    ret =send(clientfd2,&ts,sizeof(clientlist),0);
    if(ret == -1)
    {
        ERRLOG("send");
    }
    sleep(1);
    if(1==flag1)
    {
        flag1 = 0;
        selectfun();
    }
    if(0 == flag1)
    {
        funcinto();
    }
    return;
}

void privatechat()// 功能标志3 用户私聊
{
    ssize_t  ret;
    char to_name[50];
    system("clear");
    printf("\033[0;31m请输入你想私聊的对象..\033[0m\n");
    scanf("%s",ts.to_name);
    sleep(1);
    system("clear");
        ts.flag = 3;  //私聊标志为3
        char buf[200] = "\0";
        char *buf2;
        system("clear");
        printf("\033[0;31m请输入聊天内容..\033[0m\n");  //循环聊天记得加循环
        printf("\033[0;31m                               <输入Q!退出私聊>\033[0m\n");
        printf("\033[0;31m                               <输入W!查看快捷短语>\033[0m\n");
        printf("\033[0;31m                               [当前用户]:%s\033[0m\n",ts.name);
        while(1)
        {
            scanf("%s",buf);
            if(strcmp(buf,"Q!") == 0)
            {
                system("clear");
                return;
            }
            if(strcmp(buf,"W!") == 0)
            {
                phrase();
                continue;
            }
            if(flag2)
            {
                if((buf2 = selectphrase(buf)) == NULL)
                {
                    strcpy(ts.msg,buf);
                    ret =send(clientfd2,&ts,sizeof(clientlist),0);
                    if(ret == -1)
                    {
                        ERRLOG("send");
                    }
                }
                else
                {
                    strcpy(ts.msg,buf2);
                    ret =send(clientfd2,&ts,sizeof(clientlist),0);
                    if(ret == -1)
                    {
                        ERRLOG("send");
                    }
                }
            }
        }
        return;
}

void changpassword()//功能标志4 修改密码
{
    ssize_t  ret;
    char newpassword[50];
    char password[50];
    system("clear");
    printf("\033[0;31m请输入你的新密码\033[0m\n");
    system("stty -echo");
    scanf("%s",newpassword);
    system("stty echo");
    system("clear");
    printf("\033[0;31m请再次确认你的密码\033[0m\n");
    system("stty -echo");
    scanf("%s",password);
    system("stty echo");
    
    if(strcmp(password,newpassword) == 0)
    {   strcpy(ts.msg,newpassword);
        system("./zjn");
        ts.flag = 4;
        ret =send(clientfd2,&ts,sizeof(clientlist),0);
        if(ret == -1)
        {
            ERRLOG("send");
        }
        return; 
    }
    else
    {
        printf("\033[0;31m输入密码不一致请从新输入...\033[0m\n");
        sleep(1);
        changpassword();
    }
}

void groupchat() //功能标志5  群聊 显示群聊界面
{
    int num = 0;
    ssize_t ret;
    system("./zjn");
    ts.flag = 5;  //私聊标志为5
    char buf[200] = "\0";
    char *buf2;
    system("clear");
    printf("\033[0;31m请输入聊天内容..\033[0m\n");  //循环聊天记得加循环
    printf("\033[0;31m                               <输入Q!退出群聊>\033[0m\n");
    printf("\033[0;36m                               <输入W!查看快捷短语>\033[0m\n");
    printf("\033[0;36m                               <输入C!查看聊天记录>\033[0m\n");
    printf("\033[0;36m                               <输入T!进行文件传输>\033[0m\n");
    printf("\033[0;31m                               [当前用户]:%s\033[0m\n",ts.name);
    while(1)
    {   
        scanf("%s",buf);
        if(strcmp(buf,"Q!") == 0)
        {
            system("clear");
            return;
        }
        if(strcmp(buf,"W!") == 0)
        {
            phrase();
            printf("\033[0;32m请输入1继续群聊..\033[0m\n");
            scanf("%d",&num);
            if(1 == num)
            {
                break;
            }
            else
            {
                printf("\033[0;32m输入错误\033[0m\n");
            }
        }
        if(strcmp(buf,"C!") == 0)
        {
            checkrecord();
            printf("\033[0;32m请输入1继续群聊..\033[0m\n");
            scanf("%d",&num);
            if(1 == num)
            {
                break;
            }
            else
            {
                printf("\033[0;32m输入错误\033[0m\n");
            }
        }
        if(strcmp(buf,"T!") == 0)
        {
            filetransfer();
            sleep(1);
            break;
        }
        if(flag2)
        {
            if((buf2 = selectphrase(buf)) == NULL)
            {
                strcpy(ts.msg,buf);
                ret =send(clientfd2,&ts,sizeof(clientlist),0);
                if(ret == -1)
                {
                    ERRLOG("send");
                }
            }
            else
            {
                strcpy(ts.msg,buf2);
                ret =send(clientfd2,&ts,sizeof(clientlist),0);
                if(ret == -1)
                {
                    ERRLOG("send");
                }
            }
        }
    }
    groupchat();
}

void viewonline_user()//功能标志6 查看所有在线用户
{
    ts.flag = 6; 
    int ret;
    ret =send(clientfd2,&ts,sizeof(clientlist),0);
    if(ret == -1)
    {
        ERRLOG("send");
    }
    return;
}

void deleteuser() //功能标志 7 注销用户
{   
    char password[30] = {0};
    char name[30] = {0};
    printf("\033[0;31m                        请认真确认你的用户信息\033[0m\n");
    printf("\033[0;31m<输入姓名>\033[0m\n");
    scanf("%s",name);
    system("clear");
    printf("\033[0;31m<输入密码>\033[0m\n");
    scanf("%s",password);
    int ret1,ret2;
    ret1 =  strcmp(name,ts.name);
    ret2 = strcmp(password,ts.password);
    if(0 == ret1 && 0 == ret2)
    {
        ts.flag = 7; 
        int ret;
        ret =send(clientfd2,&ts,sizeof(clientlist),0);
        if(ret == -1)
        {
            ERRLOG("send");
        }
    }
}

void phrase()//快捷短语打印
{
    printf("\033[34m                  \033[0;36m🐒<快捷短语大全>\033[0;34m           \033[0m\n");
    putchar(10);
    printf("\033[34m               \033[0;36m1.<听说jsetc给分配对象?😍>\033[0;34m           \033[0m\n");

    printf("\033[34m               \033[0;36m2.<😅>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m3.<😘>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m4.<🤨>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m5.<😁>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m6.<真男人从不食💩,只食💨>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m7.<👾>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m8.< 嘟嘟嘟!! 🚋 The car is coming>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m9.<就这么点👌?>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m10.< 来🍇🍈🍊🍋多吃点,别让人看扁 >\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m11.<顺便给你分配个👩‍🍳>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m12.< Other people's money is my belongings😛 >\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m13.<Are you a dog?🐶>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m14.<你是个什么🐮🐎>\033[0;34m           \033[0m\n");
    
    printf("\033[34m               \033[0;36m15.<一个巴掌拍不响但是加上一个🍑可以>\033[0;34m           \033[0m\n");
    

}

char *selectphrase(char *num)//快捷短语选择
{
     char *buf;
    buf = (char *)malloc(32);

        if(strcmp(num,"1.")==0)
    {
        strcpy(buf,"听说jsetc给分配对象?😍");
        return buf;
    }
        if(strcmp(num,"2.")==0)
    {
        strcpy(buf,"😅");
        return buf;
    }
        if(strcmp(num,"3.")==0)
    {
        strcpy(buf,"😘");
        return buf;
    }
        if(strcmp(num,"4.")==0)
    {
        strcpy(buf,"🤨");
        return buf;
    }

        if(strcmp(num,"5.")==0)
    {
        strcpy(buf,"😁");
        return buf;
    }    
        if(strcmp(num,"6.")==0)
    {
        strcpy(buf,"真男人从不食💩,只食💨");
        return buf;
    }
        if(strcmp(num,"7.")==0)
    {
        strcpy(buf,"嘟嘟嘟!! 🚋 The car is coming");
        return buf;
    }
        if(strcmp(num,"8.")==0)
    {
        strcpy(buf,"就这么点👌?");
        return buf;
    }
        if(strcmp(num,"9.")==0)
    {
        strcpy(buf,"来🍇🍈🍊🍋多吃点,别让人看扁");
        return buf;
    }
        if(strcmp(num,"10.")==0)
    {
        strcpy(buf,"顺便给你分配个👩‍🍳");
        return buf;
    }
        if(strcmp(num,"11.")==0)
    {
        strcpy(buf,"Other people's money is my belongings😛");
        return buf;
    }
        if(strcmp(num,"12.")==0)
    {
        strcpy(buf,"Are you a dog?🐶");
        return buf;
    }
        if(strcmp(num,"13.")==0)
    {
        strcpy(buf,"你是个什么🐮🐎");
        return buf;
    }
        if(strcmp(num,"14.")==0)
    {
        strcpy(buf,"一个巴掌拍不响但是加上一个🍑可以");
        return buf;
    }
        if(strcmp(num,"15.")==0)
    {
        strcpy(buf,"👾");
        return buf;
    }
    return NULL;
}

void checkrecord()//功能标志8 查看聊天记录 
{
        ts.flag = 8; 
        int ret;
        ret =send(clientfd2,&ts,sizeof(clientlist),0);
        if(ret == -1)
        {
            ERRLOG("send");
        }
}

void  filetransfer()//功能标志9 文件传输
{
    clientlist ts1;
    strcpy(ts1.name,ts.name);
    ts1.flag = 9; 
    char filename[128];
    
    printf("\033[0;31m           <请输入要传输的文件名>\033[0m\n");
    scanf("%s",filename);
    printf("\033[0;31m           <请输入要传输的对象>\033[0m\n");
    scanf("%s",ts1.to_name);

    int bytes;
    int fd;
    if((fd = open(filename,O_RDONLY)) == -1)
    {
        perror("open error!\n");
        printf("未找到此文件");
        return;
    }
    printf("打开文件成功\n");
    while(1)
    {
        memset(ts1.buf,0,sizeof(ts1.buf));
        bytes = read(fd,ts1.buf,256);
        if(bytes == -1)
        {
            perror("read");
            return;
        }
        ts1.num = bytes;
        sleep(1);
        send(clientfd2,&ts1,sizeof(ts1),0);
        if(bytes == 0)
        {
            strcpy(ts1.buf,"0");
            send(clientfd2,&ts1,sizeof(ts1),0);
            break;
        }
    }
    close(fd);
    return;
} 

void applyroot()//功能标志 10 管理员申请
{   int num;
    putchar(10);
    printf("\033[5;;35m尊敬的管理员请选择您的专属头像\033[0m\n");
    putchar(10);
    printf("\033[33m\033[0;33m  1.👽 2.👹 3.👻 4.🐉 5.😈 6.🐸 7.🐱 8.👺             \033[0;34m     \033[0m\n");
    putchar(10);
    printf("\033[33m\033[0;33m  9.🐯 10.🐆 11.🐴 12.🐋 13.😹 14.🐮 15.🙀\033[0;34m     \033[0m\n");
    scanf("%d",&num);
    if(1 == num)
    {
        strcpy(ts.emojio,"👽");
    }
        if(2 == num)
    {
        strcpy(ts.emojio,"👹");
    }
        if(3 == num)
    {
        strcpy(ts.emojio,"👻");
    }
    if(4 == num)
    {
        strcpy(ts.emojio,"🐉");
    }
        if(5 == num)
    {
        strcpy(ts.emojio,"😈");
    }
        if(6 == num)
    {
        strcpy(ts.emojio,"🐸");
    }
        if(7 == num)
    {
        strcpy(ts.emojio,"🐱");
    }
        if(8 == num)
    {
        strcpy(ts.emojio,"👺");
    }
        if(9 == num)
    {
        strcpy(ts.emojio,"🐯");
    }
        if(10 == num)
    {
        strcpy(ts.emojio,"🐆");
    }
        if(11 == num)
    {
        strcpy(ts.emojio,"🐴");
    }
        if(12 == num)
    {
        strcpy(ts.emojio,"🐋");
    }
        if(13 == num)
    {
        strcpy(ts.emojio,"😹");
    }
        if(14 == num)
    {
        strcpy(ts.emojio,"🐮");
    }
        if(15 == num)
    {
        strcpy(ts.emojio,"🙀");
    }
    ts.flag = 10; 
    ts.root = 1;
    int ret;
    ret =send(clientfd2,&ts,sizeof(clientlist),0);
    if(ret == -1)
    {
        ERRLOG("send");
    }
    sleep(1);
    system("clear");
    if(flag1 == 2)
    {   flag1 = 0;
        selectfun();
    }
    else
    {

        printf("\033[33m     \033[0;33m申请管理员失败\033[0;34m    \033[0m\n");
        sleep(1);
        //system("clear");
        funcinto();
    }
}

void rootlogin()//功能标志11 管理员登录 登录成功直接进入管理员聊天界面
{
    ssize_t  ret;
    system("clear");
    printf("\033[0;31m请输入你的名字..\033[0m\n");
    scanf("%s",ts.name);
    system("clear");
    printf("\033[0;31m请输入你的密码\033[0m\n");
    system("stty -echo");
    scanf("%s",ts.password);
    sleep(1);
    system("stty echo");
    ts.flag = 11;  //用户登录标志位
    ret =send(clientfd2,&ts,sizeof(clientlist),0);
    if(ret == -1)
    {
        ERRLOG("send");
    }
    sleep(1);
    if(3 == flag1)
    {
        flag1 = 0;
        selectfun();
    }
    if(0 == flag1)
    {
        rootgroupchat();
    } 
    return;
}

void rootgroupchat() //管理员群聊界面 显示群聊界面
{
    usleep(500*1000);
    int num = 0;
    ts.root = 1;
    ssize_t ret;
    system("./zjn");
    ts.flag = 5;  
    char buf[200] = "\0";
    char *buf2;
    system("clear");
    printf("\033[0;31m请输入聊天内容..\033[0m\n");  //循环聊天记得加循环
    printf("\033[0;31m                             <输入Q!退出聊天室>\033[0m\n");
    printf("\033[0;36m                             <输入W!查看快捷短语>\033[0m\n");
    printf("\033[0;36m                             <输入C!查看聊天记录>\033[0m\n");
    printf("\033[0;36m                             <输入T!进行文件传输>\033[0m\n");
    printf("\033[0;36m                             <输入L!查看当前在线人数>\033[0m\n");
    printf("\033[0;36m                                               <输入K!踢人>\033[0m\n");
    printf("\033[0;36m                                               <输入F!禁言>\033[0m\n");
    printf("\033[0;36m                                               <输入U!解除禁言>\033[0m\n");
    printf("\033[0;36m                                               <输入E!撤销管理员身份>\033[0m\n");
    printf("\033[0;33m                               [管理员]😇:%s\033[0m\n",ts.name);
    while(1)
    {
        scanf("%s",buf);
        
        if(strcmp(buf,"Q!") == 0)//退出群聊
        {   
            system("clear");
            exit_room();
            return;
        }
        if(strcmp(buf,"E!") == 0)//取消管理员身份
        {   
            system("clear");
            cancelroot();
            return;
        }
        if(strcmp(buf,"W!") == 0)//查看快捷短语
        {
            phrase();
            continue;
        }
        if(strcmp(buf,"C!") == 0)//查看聊天记录
        {
            checkrecord();
            printf("\033[0;32m请输入1继续群聊..\033[0m\n");
            scanf("%d",&num);
            if(1 == num)
            {
                break;
            }
            else
            {
                printf("\033[0;32m输入错误\033[0m\n");
            }
        }
        if(strcmp(buf,"T!") == 0)//文件传输
        {
            filetransfer();
                break;
        }
        if(strcmp(buf,"L!") == 0)//查看在线用户
        {
            rootviewonline_user();
            printf("\033[0;32m请输入1继续群聊..\033[0m\n");
            scanf("%d",&num);
            if(1 == num)
            {
                break;
            }
            else
            {
                printf("\033[0;32m输入错误\033[0m\n");
            }
        }
        if(strcmp(buf,"K!") == 0)//踢人
        {
            rootkick();
                break;
        }
        if(strcmp(buf,"F!") == 0)//禁言
        {
            silent();
            break;
        }
        if(strcmp(buf,"U!") == 0)//解除禁言
        {
            remsilent();
            break;
        }
        if((buf2 = selectphrase(buf)) == NULL)
        {
            strcpy(ts.msg,buf);
            ret =send(clientfd2,&ts,sizeof(clientlist),0);
            if(ret == -1)
            {
                ERRLOG("send");
            }
            continue;
        }
        else
        {
            strcpy(ts.msg,buf2);
            ret =send(clientfd2,&ts,sizeof(clientlist),0);
            if(ret == -1)
            {
                ERRLOG("send");
            }
        }
    }
    rootgroupchat();
}

void rootviewonline_user()//管理员标志6 查看所有在线用户
{
    ts.flag = 6; 
    int ret;
    ret =send(clientfd2,&ts,sizeof(clientlist),0);
    if(ret == -1)
    {
        ERRLOG("send");
    }
    ts.flag = 5; 
    return;
}

void rootkick()//功能标志12 踢出群聊
{
    ts.root = 1;
    ssize_t  ret;
    system("clear");
    ts.flag = 12;
    printf("\033[0;31m请输入你想踢出群聊的对象..\033[0m\n");
    scanf("%s",ts.to_name);
    ret =send(clientfd2,&ts,sizeof(clientlist),0);
    if(ret == -1)
    {
        ERRLOG("send");
    }
    sleep(1);
    rootgroupchat();
    return;
    
}

void silent()//功能标志13  禁言
{
    ts.root = 1;
    ssize_t  ret;
    system("clear");
    ts.flag = 13;
    printf("\033[0;31m请输入你想禁言的对象..\033[0m\n");
    scanf("%s",ts.to_name);
    ret =send(clientfd2,&ts,sizeof(clientlist),0);
    if(ret == -1)
    {
        ERRLOG("send");
    }
    sleep(1);
    rootgroupchat();
    return;
}

void remsilent()//功能标志14  解除禁言
{
    ts.root = 1;
    ssize_t  ret;
    system("clear");
    ts.flag = 14;
    printf("\033[0;31m请输入你想解除禁言的对象..\033[0m\n");
    scanf("%s",ts.to_name);
    ret =send(clientfd2,&ts,sizeof(clientlist),0);
    if(ret == -1)
    {
        ERRLOG("send");
    }
    rootgroupchat();
    return;
}

void cancelroot()//功能标志15 取消管理员身份
{
    char password[30] = {0};
    char name[30] = {0};
    printf("\033[0;31m                        请认真确认你的用户信息\033[0m\n");
    printf("\033[0;31m<输入姓名>\033[0m\n");
    scanf("%s",name);
    system("clear");
    printf("\033[0;31m<输入密码>\033[0m\n");
    scanf("%s",password);
    int ret1,ret2;
    ret1 =  strcmp(name,ts.name);
    ret2 = strcmp(password,ts.password);
    if(0 == ret1 && 0 == ret2)
    {
        ts.flag = 15; 
        int ret;
        ret =send(clientfd2,&ts,sizeof(clientlist),0);
        if(ret == -1)
        {
            ERRLOG("send");
        }
    }
    sleep(1);
    selectfun();
    return;
}




void *recv_thread(void *arg)//接受线程函数
{   
    // int ret = 1;
    int fd;
    MSG msg;
    //int num;
    char buf[256] = {0};
    int length;
    clientfd2 = *((int *)arg);
    while(1)
    {
        memset(buf,0,sizeof(buf));
        length = recv(clientfd2,buf,sizeof(buf),0);
        if (length == 0)
        {
            pthread_exit(NULL);
            exit(1);
        }
        buf[length] = '\0';
        printf("\033[5;;36m%s\033[0m\n",buf);
        if(strcmp(buf,"该用户不存在,请注册...") == 0)
        {
            flag1 = 1;
        }
        if(strcmp(buf,"密码输入错误..") == 0)
        {
            flag1 = 1;
        }
        if(strcmp(buf,"您已在线,请勿重复登录") == 0)
        {
            flag1 = 1;
        }
        if(strcmp(buf,"管理员申请成功") == 0)
        {
            flag1 = 2;
        }
        if(strcmp(buf,"该用户非管理员") == 0)
        {
            flag1 = 3;
        }
        if(strcmp(buf,"密码输入错误") == 0)
        {
            flag1 = 3;
        }
        if(strcmp(buf,"管理员已将你踢出聊天室") == 0)
        {
            exit(1);
        }
        if(strcmp(buf,"管理员已将你禁言") == 0)
        {
            flag2 = 0;
        }
        if(strcmp(buf,"管理员已将你解除禁言") == 0)
        {
            flag2 = 1;
        }
        if(strcmp(buf,"文件存在进行文件传输") == 0)
        {   
            printf("正在接受文件\n");
            if((fd = open("1.txt",O_WRONLY | O_CREAT | O_TRUNC,0664)) == -1)
            {
                ERRLOG("open error");
            }
            int ret;
            while((ret = recv(clientfd2,&msg,sizeof(msg),0)) != -1)
            {
                //printf("ret= %d\n",ret);
                if(strcmp(msg.text,"0") == 0)
                {
                    printf("\033[0;36m文件接受完成\033[0m\n");
                    //sleep(1);
                    close(fd);
                    break;
                }
                else
                {
                    write(fd,msg.text,msg.num);
                }
                memset(&msg,0,sizeof(msg));
            }
        }
        putchar(10);
    }
    //pthread_exit(NULL);
}

void *send_thread(void *arg)//发送线程函数
{  
        selectfun();
}

void  exit_room()//退出聊天室
{
    exit(0);
}

void recvmessage()

client.h

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <sqlite3.h>
#define N 256
#define ERRLOG(errmsg) do{\
                        perror(errmsg);\
                        printf("%s - %s - %d\n",__FILE__,__func__,__LINE__);\
                        exit(1);\
                }while(0)

int clientfd2;//客户端sockfd

typedef struct file    //文件传输结构体
{
        char text[N];
        int num;
}MSG;

typedef struct client
{
        int flag; //功能标志 注册标志reg
        char emojio[20];//保存头像
        char name[32];//姓名
        int  root;    //管理员标志
        char msg[50];//聊天内容
        char password[32];//密码
        char to_name[50];//聊天对象  
        char buf[256];//文件内容
        int num;
}clientlist;
clientlist ts;


void funcinto();//第二阶段选择进入

void recvmessage();//消息接受

void n_init();//初始化客户端

void selectfun();//进入目录选择功能

void user_login();//用户登录

void user_register();//用户注册

void privatechat();//私聊

void *recv_thread(void *arg);//客户端接受消息线程函数

void *send_thread(void *arg);//客户端发送消息函数

void changpassword(); //修改密码

void groupchat(); //群聊

void viewonline_user();//查看所有在线用户 

void deleteuser();//注销用户

void phrase();//快捷短语

char *selectphrase(char *num);//快捷短语的选择

void checkrecord();//查看聊天记录

void  filetransfer();//文件传输

void applyroot();//申请成为管理员

void rootlogin();//管理员登录

void rootgroupchat();//管理员群聊界面

void rootkick();//踢出群聊

void silent();//管理员禁言

void remsilent();//解除禁言


void rootviewonline_user();//管理员查看在线用户

void cancelroot();//取消管理员身份



void root_login();//管理员登录

void  exit_room();//退出聊天室


void sendmessage();//发送字符串



网站公告

今日签到

点亮在社区的每一天
去签到