基于 Linux 的校园即时聊天软件--文件编程、网络通信、数据库实现

一:项目功能介绍

1.登录、注册、退出

2.私聊、群聊

3.查看在线用户

4.管理员权限(禁言、踢人)

5.文件传输

6.修改密码、注销账号

二:项目代码

1.服务器:

srver.h:

#ifndef _SERVER_H_
#define _SERVER_H_
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/stat.h>
#include<netinet/in.h>
#include<errno.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<string.h>
#include<fcntl.h>
#include<arpa/inet.h>
#include<errno.h>
#include<string.h>
#include<sys/time.h>
#include<sys/select.h>
#include<signal.h>
#include<sys/wait.h>
#include<sqlite3.h>
#include<time.h>
#define N 128
#define ERRLOG(errrmsg)do{\
                          perror(errrmsg);\
                          printf("%s-%s-%d\n",__FILE__,__func__,__LINE__);\
                          exit(1);\
                         }while(0)
#define PORT 9999
sqlite3 *database;
struct Msg
{
    char msg[1024];//信息内容
    int cmd;//信息类型
    char filename[50];//保存文件名
    char toname[20];//接收者姓名
    char fromname[20];//发送者姓名
    int sig;//用户状态(0:管理员,1:普通用户,2:被禁言)
    int cfd;
};

typedef int DataType;
DataType data;
#define MAX 1024
typedef struct node
{
    int cfd;
    char Name[50];
    char Port[32];
    struct node *next; 
}liaotianshi;


int z_socket();//创建套接字

int MyAccept(int sockfd);//连接客户端

void *hanld_client(void *p);//客户端请求函数

void reg(int fd,struct Msg *msg);//客户端注册请求

void log_in(int fd,struct Msg *msg);//客户端登录请求

liaotianshi *liaotianshiCreat();//创建链表

void DelContact(liaotianshi *head);//删除链表里的用户

void user_do(int fd);//处理客户端操作请求函数

void super_do(int fd);//处理客户端管理员用户操作请求函数

void quit_chatroom(int fd,struct Msg *msg);//处理客户端账号退出请求

void display(int fd,struct Msg *msg);//查看当前在线人数

void chat1(int fd,struct Msg *msg);//处理群聊信息

void chat2(int fd,struct Msg *msg);//处理私聊信息

void change_pass(int fd, struct Msg *msg);// 更改密码问题

void delete_user(int fd,struct Msg *msg);// 客户端请求在线注销

void silent(int fd, struct Msg *msg);// 处理禁言请求

void silent_del(int fd, struct Msg *msg);// 处理解除禁言请求

void kickout(int fd, struct Msg *msg);// 处理踢出成员

void sent_out(int fd,struct Msg *msg);//处理客户端传输文件


#endif

server.c:

#include"server.h"

int z_socket()
{
    //创建套接字
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in serveraddr,clientaddr;
    //填充服务器
    serveraddr.sin_family=AF_INET;
    //serveraddr.sin_addr.s_addr=inet_addr(argv[1]);
    serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
    serveraddr.sin_port=htons(8886);
    //memset(serveraddr.sin_zero,0,8);
  
    socklen_t addrlen=sizeof(serveraddr);
    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,5)==-1)
    {
        ERRLOG("listen");
    }
    printf("服务器准备就绪,等待客户端连接\n");
    return sockfd;
}

int MyAccept(int sockfd)//处理客户端连接
{
    
    //阻塞等待客户端的连接
    struct sockaddr_in serveraddr,clientaddr;
    socklen_t addrlen=sizeof(clientaddr);

    int fd;
    fd=accept(sockfd,(struct sockaddr *)&clientaddr,&addrlen);
    if(fd==-1)
    {
        ERRLOG("accept");
    }
    printf("客户端%s:%d进入了\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
    return fd;
}

void *hanld_client(void *p)//处理客户端请求的函数
{
    int fd=*(int *)p;
    struct Msg msg;
    msg.cfd = fd;
    while(1)
    {
        printf("处理客户端请求的函数已就绪\n");
        //从客户端读取一个结构体数据
        int ret=read(fd,&msg,sizeof(msg));
        if(ret==-1)
        {
            perror("read");
            break;
        }
        //代表客户端退出
        if(ret==0)
        {
            printf("客户端退出了\n");
            //DelContact(head);
            break;
        }
        switch(msg.cmd)
        {
            case 1://客户端注册
            reg(fd,&msg);
            break;
            case 2://客户端登录
            log_in(fd,&msg);
            break;
        }
    }
    close(fd);
}

void reg(int fd,struct Msg *msg)//客户端注册请求
{
    printf("%s进行注册\n",msg->fromname);
    //将用户进行保存
    //打开数据库
    int ret=sqlite3_open("User.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败\n");
        msg->cmd=-2;
        write(fd,msg,sizeof(struct Msg));
        return;
    }
    //往User表中添加信息
    //与user1表中信息进行对比
    char buf[1500];
    memset(buf,0,1500);
    char *errmsg=NULL;
    char **result=NULL;
    int nrow,ncolumn;//行数,列数
    int j;
    char *sql="select *from user";
    ret=sqlite3_get_table(database,sql,&result,&nrow,&ncolumn,&errmsg);
    for(j=0;j<(nrow+1)*ncolumn;j+=5)
    {
        if(strcmp(result[j],msg->fromname)==0)
        {
            msg->cmd=-5;
            write(fd,msg,sizeof(struct Msg));
            return;
        }
    }
    sprintf(buf,"insert into user values('%s','%s',%d,%d,%d)",msg->fromname,msg->msg,fd,0,msg->sig);
    ret=sqlite3_exec(database,buf,NULL,NULL,&errmsg);
    if(ret!=SQLITE_OK)
    {
        printf("数据库操作失败\n");
        msg->cmd=-1;
        write(fd,msg,sizeof(struct Msg));
        return;
    }
    
    msg->cmd=1001;
    printf("%s注册成功\n",msg->fromname);
    write(fd,msg,sizeof(struct Msg));
    //关闭数据库
    sqlite3_close(database);
    printf("操作完成,已关闭数据库\n");

}

liaotianshi *liaotianshiCreat()//创建链表
{
    liaotianshi *head = (liaotianshi *)malloc(sizeof(liaotianshi));
    head->next = NULL;
    return head;
}

void log_in(int fd,struct Msg *msg)//客户端登录请求
{
    printf("%s请求登录\n",msg->fromname);
    //将用户信息进行对比
    //打开数据库
    int ret=sqlite3_open("User.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败\n");
        msg->cmd=-2;
        write(msg->cfd,msg,sizeof(struct Msg));
        return;
    } 
    //与user1表中信息对比
    char *errmsg1=NULL;
    char **result1;
    int nrow1,ncolumn1;//行数,列数
    char *sql1="select *from user1";
    ret=sqlite3_get_table(database,sql1,&result1,&nrow1,&ncolumn1,&errmsg1);
    if(ret!=SQLITE_OK)
    {
        printf("数据库操作失败%s\n",errmsg1);
        msg->cmd=-1;
        write(msg->cfd,msg,sizeof(struct Msg));
        return;
    }
    int j;
    for(j=0;j<(nrow1+1)*ncolumn1;j+=5)
    {
        if(strcmp(result1[j],msg->fromname)==0 && strcmp(result1[j+1],msg->msg)==0)
        {
            msg->cmd=-4;
            printf("%s该账号已经在别处登录\n",msg->fromname);
            write(msg->cfd,msg,sizeof(struct Msg));
            sqlite3_free_table(result1);
            sqlite3_close(database);
            printf("操作成功,已关闭数据库\n");
            return;
        }
    }
    sqlite3_free_table(result1);
    //与User表中信息进行对比
    char *errmsg=NULL;
    char **result;
    int nrow,ncolumn;//行数,列数
    char *sql="select *from user";
    ret=sqlite3_get_table(database,sql,&result,&nrow,&ncolumn,&errmsg);
    if(ret!=SQLITE_OK)
    {
        printf("数据库操作失败%s\n",errmsg);
        msg->cmd=-1;
        write(msg->cfd,msg,sizeof(struct Msg));
        return;
    }
    int i;
    for(i=0;i<(nrow+1)*ncolumn;i+=5)
    {

        
        //char Buf[]="wal";
        //char Buf1[]="123";
        char buf1[1500];
        memset(buf1,0,1500);
        //if(strcmp(Buf,msg->fromname)==0 && strcmp(Buf1,msg->msg)==0)
        if(strcmp(result[i],msg->fromname)==0 && strcmp(result[i+1],msg->msg)==0)
        {
            if(strcmp(result[i+4],"0") == 0)
            {
                msg->cmd=1003;
                printf("管理员%s核验通过\n",msg->fromname);
                int ret;
                //ret=write(msg->cfd,msg,sizeof(struct Msg));
                //printf("%d\n",ret);

                char *errmsg=NULL; 
                //msg->sig=0; 
                sprintf(buf1,"insert into user1 values('%s','%s',%d,%d,%d)",msg->fromname,msg->msg,msg->cfd,0,msg->sig);
                ret=sqlite3_exec(database,buf1,NULL,NULL,&errmsg);
                if(ret!=SQLITE_OK)
                {
                    printf("数据库操作失败\n");
                    msg->cmd=-1;
                    write(msg->cfd,msg,sizeof(struct Msg));
                    sqlite3_close(database);
                    return;
                }
                sleep(2);
                write(msg->cfd,msg,sizeof(struct Msg));
                sqlite3_free_table(result);
                sqlite3_close(database);
                printf("操作完成,已关闭数据库\n");
                
                super_do(fd);
                
                return;
                
            }
            else
            {
                msg->cmd=1002;
                printf("普通用户%s验证通过\n",msg->fromname);
                //write(msg->cfd,msg,sizeof(struct Msg)); 
                //sleep(2);
                //msg->sig=1;
                char *errmsg=NULL;
                sprintf(buf1,"insert into user1 values('%s','%s',%d,%d,%d)",msg->fromname,msg->msg,msg->cfd,0,msg->sig);
                ret=sqlite3_exec(database,buf1,NULL,NULL,&errmsg);
                if(ret!=SQLITE_OK)
                {
                    printf("数据库操作失败\n");
                    msg->cmd=-1;
                    write(msg->cfd,msg,sizeof(struct Msg));
                    sqlite3_close(database);
                    return;
                }
                sleep(2);
                write(msg->cfd,msg,sizeof(struct Msg));
                sqlite3_free_table(result);
                sqlite3_close(database);
                printf("操作完成,已关闭数据库\n");    
                user_do(fd);
                sleep(4);    
                return;
            }
        }  
    }
    printf("%s核验不通过\n",msg->fromname);
    msg->cmd=-3;
    write(msg->cfd,msg,sizeof(struct Msg));
    sqlite3_free_table(result);
    sqlite3_close(database);
    printf("操作完成,已关闭数据库\n");  
}

void user_do(int fd)//处理客户端普通用户操作请求函数
{
    struct Msg msg;
	
    int sig=0;
    while(1)
    {
        //从客户端读取一个结构体数据
        int ret=read(fd,&msg,sizeof(msg));
        if(ret==-1)
        {
            perror("read");
            break;
        }
        //代表客户端退出
        /*if(ret==0)
        {
            printf("客户端返回登录界面\n");
            break;
        }*/
        //printf("%d\n",msg.cmd);
        switch(msg.cmd)
        {
            case 1://查看在线人数
            display(fd,&msg);
            break;
            case 2://处理群聊界面
            chat1(fd,&msg);
            break;
            case 3://处理私聊界面
            chat2(fd,&msg);
            break;
            case 5://处理客户端传输文件
            sent_out(fd,&msg);
            break;
            case 6://处理更改密码
            change_pass(fd,&msg);
            break;
            case 7://处理在线注销
            sig=1;
            delete_user(fd,&msg);
            break;
            case 9://退出聊天室 返回登录界面
            quit_chatroom(fd,&msg);      
            sig=1;
            break;
        }
        if(sig==1)
        {
            printf("即将退出普通用户操作请求函数\n");
            break;
        }

    }
}

void super_do(int fd)//处理客户端管理员用户操作请求函数
{
    struct Msg msg;
	//struct Msg msg;
	//memset(&msg, 0, sizeof(msg));
    int sig=0;
    while(1)
    {
        //printf("1233\n");
        //从客户端读取一个结构体数据
        int ret=read(fd,&msg,sizeof(msg));
        if(ret==-1)
        {
            perror("read");
            break;
        }
        //代表客户端退出
        /*if(ret==0)
        {
            printf("客户端返回登录界面\n");
            break;
        }*/
        //printf("%d ttttttttttttttttttttttttttttt\n",msg.cmd);
        switch(msg.cmd)
        {
            case 1://查看在线人数
            display(fd,&msg);
            break;
            case 2://处理群聊界面
            chat1(fd,&msg);
            break;
            case 3://处理私聊界面
            chat2(fd,&msg);
            break;
            case 5://处理客户端传输文件
            sent_out(fd,&msg);
            break;
            case 6://处理更改密码
            change_pass(fd,&msg);
            break;
            case 7://处理在线注销
            sig=1;
            delete_user (fd,&msg);
            break;
            case 9://退出聊天室 返回登录界面
            sig=1;
            quit_chatroom(fd,&msg);         
            break;
            case 9011:// 处理禁言请求
            silent(fd,&msg);
            break;
            case 9012://处理解除禁言问题
            silent_del(fd,&msg);
            break;
            case 9013://管理员踢出普通用户
            kickout(fd,&msg);
            break;
        }
        if(sig==1)
        {
            printf("即将退出管理员用户操作请求函数\n");
            break;
        }

    }
}

void quit_chatroom(int fd,struct Msg *msg)//处理客户端账号退出请求
{
    printf("%s退出聊天室\n",msg->fromname);
    //打开数据库
    int ret=sqlite3_open("User.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败\n");
        return;
    }
    char buf[100];
    char *errmsg=NULL;
    errmsg=NULL;
    memset(buf,0,sizeof(buf));
    sprintf(buf,"delete from user1 where name = '%s'",msg->fromname);
    ret=sqlite3_exec(database,buf,NULL,NULL,&errmsg);
    if(ret!=SQLITE_OK)
    {
        printf("数据库操作失败%s\n",errmsg);
        return;
    }
    sqlite3_close(database);
    printf("删除数据库内容成功\n");
    write(fd,msg,sizeof(struct Msg));
}

void display(int fd,struct Msg *msg)//查看当前在线人数
{
    printf("当前的人数为\n");
    //确定flag参数
    //打开数据库
    int ret=sqlite3_open("User.db",&database);
    printf("1\n");
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败\n");
        msg->cmd=-2;
        write(fd,msg,sizeof(struct Msg));
        return;
    }
    printf("2\n");
    //与user1表中信息进行对比
    char *errmsg=NULL;
    char **result=NULL;
    int nrow,ncolumn;//行数,列数
    char *sql1="select *from user1";
    ret=sqlite3_get_table(database,sql1,&result,&nrow,&ncolumn,&errmsg);
    printf("3\n");
    if(ret!=SQLITE_OK)
    {
        printf("数据库操作失败%s\n",errmsg);
        msg->cmd=-1;
        write(msg->cfd,msg,sizeof(struct Msg));
        return;
    }
    int j;
    //int count=0;
    char buf[100];
    memset(buf,0,100);
    printf("5\n");
    for(j=5;j<(nrow+1)*ncolumn;j+=5)
    {
        strcpy(buf,result[j]);
    }
    printf("6\n");
    printf("%s\n",buf);
    strcpy(msg->msg,buf);
    printf("%s\n",msg.msg);
    printf("7\n");
    msg->cmd=8888;
    printf("8\n");
    write(fd,msg,sizeof(struct Msg));
    sqlite3_free_table(result);
    sqlite3_close(database);
    printf("操作完成,已关闭数据库\n");
}

void chat1(int fd,struct Msg *msg)//处理群聊信息
{
    printf("%s发了一条信息%s \n",msg->fromname,msg->msg);
    //打开数据库
    int ret=sqlite3_open("User.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败\n");
        msg->cmd=-2;
        write(fd,msg,sizeof(struct Msg));
        return;
    }
    //获取数据库中的flag信息
    char *errmsg=NULL;
    char **result=NULL;
    int nrow,ncolumn;//行数,列数
    char *sql1="select *from user1";
    ret=sqlite3_get_table(database,sql1,&result,&nrow,&ncolumn,&errmsg);
    if(ret!=SQLITE_OK)
    {
        printf("数据库操作失败\n");
        msg->cmd=-1;
        write(fd,msg,sizeof(struct Msg));
        return;
    }
    int j;
    for(j=0;j < (nrow+1) * ncolumn;j += 5)
    {
        if(strcmp(result[j],msg->fromname)!=0)
        {
            msg->cmd=9001;
            write(atoi(result[j+2]),msg,sizeof(struct Msg));
        }
    }
    printf("群信息已经全部发送完成\n");
    sqlite3_close(database);
    printf("操作完成,已关闭数据库\n");

}

void chat2(int fd,struct Msg *msg)//处理私聊问题
{
    printf("%s 向 %s 发了一条信息 %s\n",msg->fromname,msg->toname,msg->msg);
    //打开数据库
    int ret=sqlite3_open("User.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败\n");
        msg->cmd=-2;
        write(fd,msg,sizeof(struct Msg));
        return;
    }
    //获取数据库中的flag参数信息,判断是否在线
    char *errmsg=NULL;
    char **result=NULL;
    int nrow,ncolumn;//行数,列数
    char *sql1="select *from user1";
    ret=sqlite3_get_table(database,sql1,&result,&nrow,&ncolumn,&errmsg);
    if(ret!=SQLITE_OK)
    {
        printf("数据库操作失败\n");
        msg->cmd=-1;
        write(fd,msg,sizeof(struct Msg));
        return;
    }
    
    int i;
    for(i=0;i<(nrow+1)*ncolumn;i+=5)
    {
        if(strcmp(result[i],msg->toname)==0)
        {
            msg->cmd=9002;
            write(atoi(result[i+2]),msg,sizeof(struct Msg));
            return;
        }
    }
    msg->cmd=9003;
    write(fd,msg,sizeof(struct Msg));
    sqlite3_close(database);
    printf("操作完成,已关闭数据库\n");

}

void change_pass(int fd, struct Msg *msg)// 更改密码问题
{
    printf ("%s请求修改密码\n", msg->fromname);

    // 打开数据库
    int ret = sqlite3_open("User.db", &database);
    if (ret != SQLITE_OK)
    {
        printf ("打开数据库失败\n");
        msg->cmd = -2;
        write (fd, msg, sizeof(struct Msg));
        return;
    }

    // 与User表中信息进行比对
    char *errmsg = NULL;
    char **result = NULL;
    int nrow, ncolumn;
    char *sql = "select * from user";
    ret = sqlite3_get_table(database, sql, &result, &nrow, &ncolumn, &errmsg);
    if (ret != SQLITE_OK)
    {
        printf ("数据库操作失败:%s\n", errmsg);
        return;
    }
    int i;
    for (i = 0+ncolumn; i < (nrow+1)*ncolumn; i+=ncolumn)
    {
        if(strcmp(result[i], msg->fromname)==0 && strcmp(result[i+1], msg->msg)==0)
        {
            // 返回确认信息
            msg->cmd = 9009;
            printf ("%s 验证通过\n", msg->fromname);
            write (fd, msg, sizeof(struct Msg));

            // 修改密码
            char buf[200];
            memset(buf,0,200);
            errmsg = NULL;
            sprintf(buf, "update user set password = '%s' where name = '%s'",msg->filename,msg->fromname);
            ret = sqlite3_exec(database, buf, NULL, NULL, &errmsg);
            if (ret != SQLITE_OK)
            {
                printf("数据库操作失败:%s\n", errmsg);
                return;
            }
            sqlite3_free_table(result);

            // 关闭数据库
            sqlite3_close(database);
            printf ("密码修改完成,已关闭数据库\n");
            return;
        }
    }   
    printf ("%s 验证不通过,密码输入有误\n", msg->fromname);
    msg->cmd = 9010;
    write (fd, msg, sizeof(struct Msg));
    sqlite3_free_table(result);
    // 关闭数据库
    sqlite3_close(database);
    printf ("操作完成,已关闭数据库\n");           

}

void delete_user (int fd, struct Msg *msg)// 客户端请求在线注销
{
    printf ("即将处理用户注销\n");

    // 打开数据库
    int ret = sqlite3_open("User.db", &database);
    if (ret != SQLITE_OK)
    {
        printf ("打开数据库失败\n");
        return;
    }

    // 删除 user 表中的信息
    char buf[100];
    char *errmsg = NULL;
    sprintf (buf, "delete from user where name = '%s'", msg->fromname);
    ret = sqlite3_exec(database, buf, NULL, NULL, &errmsg);
    if (ret != SQLITE_OK)
    {
        printf ("数据库操作失败:%s\n", errmsg);
        return;
    }
    memset(buf,0,100);
    sprintf (buf, "delete from user1 where name = '%s'", msg->fromname);
    ret = sqlite3_exec(database, buf, NULL, NULL, &errmsg);
    if (ret != SQLITE_OK)
    {
        printf ("数据库操作失败:%s\n", errmsg);
        return;
    }

    // 关闭数据库
    sqlite3_close(database);
    printf ("删除成功,已关闭数据库\n");
}

void silent(int fd, struct Msg *msg)// 处理禁言请求
{
    printf("正在处理管理员 %s 对成员 %s 的禁言请求\n",msg->fromname,msg->toname);

    // 打开数据库
    int ret = sqlite3_open("User.db", &database);
    if (ret != SQLITE_OK)
    {
        printf ("打开数据库失败\n");
        msg->cmd = -2;
        write (fd, msg, sizeof(struct Msg));
        return;
    }

    // 获取数据库中的 flag 参数信息,判断是否在线
    char *errmsg = NULL;
    char **resultp = NULL;
    int nrow, ncolumn;
    char *sql = "select * from user1";
    ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
    if (ret != SQLITE_OK)
    {
        printf ("数据库操作失败:%s\n", errmsg);
        msg->cmd = -1;
        write (fd, msg, sizeof(struct Msg));
        return;
    }
    // 获取toname的套接字
    int i;
    for (i = 0; i < (nrow+1)*ncolumn; i+=5)
    {
        if(strcmp(resultp[i], msg->toname)==0)
        {
            msg->cmd =  9011;
            write (atoi(resultp[i+2]), msg, sizeof(struct Msg));

            char buf[100];
            memset(buf,0,100);
            errmsg = NULL;
            sprintf (buf, "update user1 set sig = 2 where name = '%s'",msg->toname);
            ret = sqlite3_exec(database, buf, NULL, NULL, &errmsg);
            if (ret != SQLITE_OK)
            {
                printf ("数据库操作失败:%s\n", errmsg);
                return;
            }
            sqlite3_close(database);
            printf ("禁言状态修改完毕,已关闭数据库\n");
            return;
        }
    }
    msg->cmd = 9003;
    write (fd, msg, sizeof(struct Msg));
    sqlite3_close(database);
    printf ("用户不在线,修改失败,已关闭数据库\n");
}

void silent_del(int fd, struct Msg *msg)// 处理解除禁言请求
{
    printf ("正在处理管理员 %s 对成员 %s 的解除禁言请求\n",msg->fromname,msg->toname);

    // 打开数据库
    int ret = sqlite3_open("User.db", &database);
    if (ret != SQLITE_OK)
    {
        printf ("打开数据库失败\n");
        msg->cmd = -2;
        write (fd, msg, sizeof(struct Msg));
        return;
    }

    // 获取数据库中的 flag 参数信息,判断是否在线
    char *errmsg = NULL;
    char **resultp = NULL;
    int nrow, ncolumn;
    char *sql = "select * from user1";
    ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
    if (ret != SQLITE_OK)
    {
        printf ("数据库操作失败:%s\n", errmsg);
        msg->cmd = -1;
        write (fd, msg, sizeof(struct Msg));
        return;
    }
    // 获取toname的套接字
    int i;
    for (i = 0; i < (nrow+1)*ncolumn; i+=5)
    {
        if(strcmp(resultp[i], msg->toname)==0)
        {
            msg->cmd =  9012;
            write (atoi(resultp[i+2]), msg, sizeof(struct Msg));
            char buf[100];
            errmsg = NULL;
            sprintf (buf, "update user1 set sig = 1 where name = '%s'",msg->toname);
            ret = sqlite3_exec(database, buf, NULL, NULL, &errmsg);
            if (ret != SQLITE_OK)
            {
                printf ("数据库操作失败:%s\n", errmsg);
                return;
            }
            sqlite3_close(database);
            printf ("禁言状态修改完毕,已关闭数据库\n");

            return;
        }
    }
    msg->cmd = 9003;
    write(fd, msg, sizeof(struct Msg));
    sqlite3_close(database);
    printf ("用户不在线,修改失败,已关闭数据库\n"); 

}

void kickout(int fd, struct Msg *msg)// 处理踢出成员
{
    printf ("正在处理管理员 %s 对成员 %s 的踢出请求\n",msg->fromname,msg->toname);

    // 打开数据库
    int ret = sqlite3_open("User.db", &database);
    if (ret != SQLITE_OK)
    {
        printf ("打开数据库失败\n");
        msg->cmd = -2;
        write (fd, msg, sizeof(struct Msg));
        return;
    }

    // 获取数据库中的 flag 参数信息,判断是否在线
    char *errmsg = NULL;
    char **resultp = NULL;
    int nrow, ncolumn;
    char *sql = "select * from user1";
    ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
    if (ret != SQLITE_OK)
    {
        printf ("数据库操作失败:%s\n", errmsg);
        return;
    }
    // 获取toname的套接字
    int i;
    for (i = 0; i < (nrow+1)*ncolumn; i+=5)
    {
        if(strcmp(resultp[i], msg->toname)==0)
        {
            msg->cmd =  9013;
            write (atoi(resultp[i+2]), msg, sizeof(struct Msg));

            char buf[100];
            memset(buf,0,100);
            errmsg = NULL;
            //sprintf (buf, "update user set flag = 0 where name = '%s'",msg->toname);
            sprintf(buf,"delete from user1 where name = '%s'",msg->toname);
            ret = sqlite3_exec(database, buf, NULL, NULL, &errmsg);
            if (ret != SQLITE_OK)
            {
                printf ("数据库操作失败:%s\n", errmsg);
                return;
            }
            sqlite3_close(database);
            printf ("踢出完毕,已关闭数据库\n");

            return;
        }
    }
    msg->cmd = 9003;
    write (fd, msg, sizeof(struct Msg));
    sqlite3_close(database);
    printf ("用户不在线,修改失败,已关闭数据库\n"); 
}


int main(int argc, char const *argv[])
{   
    int sockfd=z_socket();//初始化套接字
    int ret=sqlite3_open("User.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败\n");
        return -1;
    }
    //创建user表
    char *errmsg = NULL;
    char *sql = "create table if not exists user(name TEXT,password TEXT,socket INTEGER,flag INTEGER,sig INTEGER,primary key(name))";
    ret = sqlite3_exec(database, sql, NULL, NULL, &errmsg);
    if (ret != SQLITE_OK)
    {
        printf("打开数据库失败\n");
        return -1;
    }
    //创建保存登录用户的表
    //char *errmsg=NULL;
    char *sql1="create table if not exists user1(name TEXT,password TEXT,socket INTEGER,flag INTEGER,sig INTEGER,primary key(name))";
    //char *sql1="create table if not exists user1(name TEXT,password TEXT)";
    ret=sqlite3_exec(database,sql1,NULL,NULL,&errmsg);
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败\n");
        return -1;
    }
    printf("数据库准备就绪....\n");
    sqlite3_close(database);
    
    while(1)
    {
        //获取与客户端连接的套接字
        int fd=MyAccept(sockfd);
        //创建一个线程去处理客户端的请求
        pthread_t tid;
        pthread_create(&tid, NULL, hanld_client,&fd);
        pthread_detach(tid);//线程分离
    }
    close(sockfd);
    
    return 0;
}

sent_out.c:

#include"server.h"
void sent_out(int fd,struct Msg *msg)//处理客户端传输文件请求
{
    printf("%s向%s发送了一个文件%s\n",msg->fromname,msg->toname,msg->filename);
    printf("%s\n",msg->msg);
    int ret=sqlite3_open("User.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败\n");
        msg->cmd=-2;
        write(fd,msg,sizeof(struct Msg));
        return;
    }
    //获取数据库中的flag信息
    char *errmsg=NULL;
    char **result=NULL;
    int nrow,ncolumn;//行数,列数
    char *sql1="select *from user1";
    ret=sqlite3_get_table(database,sql1,&result,&nrow,&ncolumn,&errmsg);
    if(ret!=SQLITE_OK)
    {
        printf("数据库操作失败\n");
        msg->cmd=-1;
        write(fd,msg,sizeof(struct Msg));
        return;
    }
    int j;
    for(j=0;j < (nrow+1) * ncolumn;j += 5)
    {
        if(strcmp(result[j],msg->toname)==0)
        {
            msg->cmd=9008;
            //printf("%s\n",msg->msg);
            write(atoi(result[j+2]),msg,sizeof(struct Msg));
        }
    }
    msg->cmd=9003;
    write(fd,msg,sizeof(struct Msg));
    sqlite3_close(database);
    printf("操作完成,已关闭数据库\n");
}

makefile:

run:
	gcc *.c -lpthread -lsqlite3 -o run

2:客户端

client.h:

#ifndef _CLIENT_H_
#define _CLIENT_H_
#include<stdio.h>
#include<sqlite3.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/stat.h>
#include<netinet/in.h>
#include<errno.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<string.h>
#include<fcntl.h>
#include<arpa/inet.h>
#include<errno.h>
#include<string.h>
#include<sys/time.h>
#include<sys/select.h>
#include<signal.h>
#include<sys/wait.h>
#include<time.h>

#define N 128
#define ERRLOG(errrmsg)do{\
                          perror(errrmsg);\
                          printf("%s-%s-%d\n",__FILE__,__func__,__LINE__);\
                          exit(1);\
                         }while(0)
#define PORT 9999
//char myName[20];//保存用户名
//char msg1[1200];//保存聊天信息
//char msg2[1500];//保存私聊信息
sqlite3 *database;
//int flag1=0;//线程退出的判断条件(不退出)
//int flag2=0;//文件传输确认信号(误接收)
//int flag3=0;//存在文件接收请求的判断(不存在)
//int flag4=0;//本地存储是否被禁言(未被禁言)
struct Msg//协议
{
    char msg[1024];//信息内容
    int cmd;//信息类型
    char filename[50];//保存文件名
    char toname[20];//接收者姓名
    char fromname[20];//发送者姓名
    int sig;//用户状态(0:管理员,1:普通用户,2:被禁言)
};
struct Msg msg;//全局变量两个线程共享
int sockfd;

void menu1();//用户登录页面

void menu2();//普通用户页面

void menu3();//管理员界面

void menu4();//管理员操作界面

int z_socket();//创建套接字

void ask_server(int sockfd);//向服务器发送请求

void reg(int sockfd);//注册用户

void log_in(int sockfd);//登录用户

void *readMsg(void *p);//用来监听收到的信息

void super_do(int sockfd);//管理员用户操作

void user_do(int sockfd);//普通用户登录

void quit_chatroom(int sockfd);//退出聊天室,返回登录界面

void display(int sockfd);//查看当前在线人数

void chat1(int sockfd);//群聊界面

void chat2(int sockfd);//私聊界面

void keep_msg(char *msg1);//用来保存收到的群聊记录

void keep_msg2(char *msg2);//用来保存私聊信息

void dis_history(int sockfd);//查看聊天记录

void chat1_hst();//打印群聊信息

void chat2_hst();//打印群聊信息

void change_pass(int sockfd);//修改密码

void delete_user(int sockfd);// 在线注销

void supuser(int sockfd);//管理员权限界面

void silent(int sockfd);// 将成员禁言

void silent_del(int sockfd);// 将成员解除禁言

void kickout (int sockfd);// 将成员踢出聊天室

void sent_out(int sockfd);//向服务器发送文件

void Receive(char *msg3);//接收文件



#endif

main.c

#include"client.h"
extern int flag1;//线程退出的判断条件(不退出)
int main(int argc, char const *argv[])
{
    z_socket();
    //打开数据库
    int ret=sqlite3_open("histroy.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败\n");
        return -1;
    }
    //创建histroy表,保存群聊信息
    char *errmsg=NULL;
    char *sql="create table if not exists histroy(fromname TEXT,msg1 TEXT)";
    ret=sqlite3_exec(database,sql,NULL,NULL,&errmsg);
    if(ret!=SQLITE_OK)
    {
        printf("打开数据库失败%s\n",errmsg);
        return -1;
    }
    //创建histroy1表,保存私聊信息
    char *sql1 = "create table if not exists histroy1(fromname TEXT,toname TEXT,msg2 TEXT)";
    ret = sqlite3_exec(database, sql1, NULL, NULL, &errmsg);
    if (ret != SQLITE_OK)
    {
        printf("打开数据库失败\n");
        return -1;
    }

    sqlite3_close(database);//关闭数据库
    //线程分离,用来监听服务器返回信息
    pthread_t tid;
    pthread_create(&tid,NULL,readMsg,&sockfd);
    pthread_detach(tid);
    char ch[2];
START:   
    while(1)
    {    
        menu1();
        fgets(ch,2,stdin);
        while(getchar()!='\n');
        switch(ch[0])
        {
            case 'a':
            reg(sockfd);
            break;
            case 'b':
            log_in(sockfd);
            struct Msg msg;
	        //memset(&msg, 0, sizeof(msg));
            //sleep(2);
            //printf("12345\n");
            read(sockfd,&msg,sizeof(struct Msg));
            //printf("qwert\n");
            if(msg.cmd==1002)
            {
                printf("\n\t普通用户校验通过,正在登录...\n");
                usleep(1500000);
                while(1)
                {
                    menu2();
                    fgets(ch,2,stdin);
                    while(getchar()!='\n');
                    switch(ch[0])
                    {
                        case '1'://查看在线人数
                        display(sockfd);
                        break;
                        case '2'://进入群聊界面
                        chat1(sockfd);
                        printf("\n\t回车键返回 \n");
                        getchar();
                        break;
                        case '3'://进入私聊界面
                        chat2(sockfd);
                        printf("\n\t回车键返回 \n");
                        getchar();
                        break;
                        case '4'://查看聊天记录
                        dis_history(sockfd);
                        getchar();
                        break;
                        case '5'://文件传输
                        sent_out(sockfd);
                        break;
                        case '6'://更改密码
                        change_pass(sockfd);
                        break;
                        case '7'://在线注销
                        printf ("\n\t是否确认注销?(y/n):   ");
                        fgets(ch, 2, stdin);
                        while (getchar()!= '\n');
                        if (ch[0] != 'y')
                        {
                            printf ("\n\t请稍候.....\n");
                            usleep(700000);
                            break;
                        }
                        flag1==1;
                        delete_user(sockfd);
                        printf("\n\t正在退出,请稍候...\n");
                        goto START;
                        break;
                        case '9'://退出聊天室 返回登录界面
                        flag1=1;
                        quit_chatroom(sockfd);
                        printf("\n\t正在退出,请稍候...\n");
                        printf("\n\t普通用户退出成功\n");
                        sleep(2);
                        goto START;
                        break;
                    }
                    if(flag1==1)//判断退出条件
                    {
                        break;
                    }
                    system("clear");
                }    
            }
            if(msg.cmd==1003)
            {
                printf("\n\t管理员用户校验通过,正在登录...\n");
                usleep(1500000);
                //printf("管理员用户\n");
                //char ch[2];
                while(1)
                {
                    menu3();
                    fgets(ch,2,stdin);
                    while(getchar()!='\n');
                    switch(ch[0])
                    {
                        case '1'://查看在线人数
                        display(sockfd);
                        break;
                        case '2'://进入群聊界面
                        chat1(sockfd);
                        printf("\n\t回车键返回 \n");
                        getchar();
                        break;
                        case '3'://进入私聊界面
                        chat2(sockfd);
                        printf("\n\t回车键返回 \n");
                        getchar();
                        break;
                        case '4'://查看聊天记录
                        dis_history(sockfd);
                        getchar();
                        break;
                        case '5'://文件传输
                        sent_out(sockfd);
                        break;
                        case '6'://更改密码
                        change_pass(sockfd);
                        break;
                        case '7'://在线注销
                        printf ("\n\t是否确认注销?(y/n):   ");
                        fgets(ch, 2, stdin);
                        while (getchar()!= '\n');
                        if (ch[0] != 'y')
                        {
                            printf ("\n\t请稍候.....\n");
                            usleep(700000);
                            break;
                        }
                        flag1=1;
                        delete_user(sockfd);
                        printf("\n\t正在退出,请稍候...\n");
                        sleep(2);
                        goto START;
                        break;
                        case '8'://管理员界面
                        supuser(sockfd);
                        break;
                        case '9'://退出聊天室 返回登录界面
                        flag1=1;
                        quit_chatroom(sockfd);
                        printf("\n\t正在退出,请稍候...\n");
                        printf("\n\t管理员退出成功!\n");
                        sleep(2);
                        goto START;
                        break;
                    }
                    if(flag1==1)//判断退出条件
                    {
                        break;
                    }
                    system("clear");
                }
            }
                
            if(msg.cmd==-4)
            {
                printf("\n\t此账号已在别处登录\n");
            }
            if(msg.cmd==-3)
            {
                printf("\n\t验证失败,请您确定信息后重新登录\n");
            }
            if(msg.cmd==-2)
            {
                printf("\n\t验证失败,数据库打开失败\n");
            }
            if(msg.cmd==-1)
            {
                printf("\n\t数据库操作失败\n");
            }
            usleep(1500000);
            break;
            case 'c':
            printf("\n\t退出聊天室\n");
            //pthread_exit(NULL);
            exit(1);
        }   
    }
    close(sockfd);
    
}

client.c:

#include"client.h"
int flag1=0;//线程退出的判断条件(不退出)
int flag2=0;//文件传输确认信号(误接收)
int flag3=0;//存在文件接收请求的判断(不存在)
int flag4=0;//本地存储是否被禁言(未被禁言)
char myName[20];//保存用户名
char msg1[1200];//保存聊天信息
char msg2[1500];//保存私聊信息
char msg3[1500];//保存文件内容
void menu1()//登录界面
{
    system("clear");
    printf("\t\033[1;31;40m***********网络聊天室***********\033[0m\n");
    printf("\t\033[1;31;40m                              \033[0m\n");
    printf("\t\033[1;32;40m*          a.注册               \n");
    printf("\t\033[1;32;40m*          b.登录               \n");
    printf("\t\033[1;32;40m*          c.退出               \n");
    printf("\t                                \n");
    printf("\t                                \n");
    printf("\t\033[1;31;40m**********************************\033[0m\n");
    printf("\t------>请输入命令\n");
}

void menu2()//普通用户界面
{
    system("clear");
    printf("\t\033[1;31;40m*****************网络聊天室***************\033[0m\n");
    printf("\t                                        \n");
    printf("\t\033[1;32;40m*           1.查看当前在线用户             \033[0m\n");
    printf("\t\033[1;32;40m*           2.进入群聊界面                \033[0m\n");
    printf("\t\033[1;32;40m*           3.进入私聊界面                \033[0m\n");
    printf("\t\033[1;32;40m*           4.查看聊天记录                \033[0m\n");
    printf("\t\033[1;32;40m*           5.文件传输                   \033[0m\n");
    printf("\t\033[1;32;40m*           6.更改密码                   \033[0m\n");
    printf("\t\033[1;32;40m*           7.在线注销                   \033[0m\n");
    printf("\t\033[1;32;40m*           9.退出聊天室 返回登录界面      \033[0m\n");
    printf("\t\033[1;32;40m*                                       \033[0m\n");
    printf("\t\033[1;31;40m****************************************\033[0m\n");
    printf("\t------>请输入命令\n");
}

void menu3()//管理员用户界面
{
    system("clear");
    printf("\t\033[1;36;40m*****************网络聊天室***************\033[0m\n");
    printf("\t                                        \n");
    printf("\t\033[5;35;40m        管理员:                               \033[0m\n");
    printf("\t\033[5;33;40m*           1.查看当前在线用户             \033[0m\n");
    printf("\t\033[5;33;40m*           2.进入群聊界面                \033[0m\n");
    printf("\t\033[5;33;40m*           3.进入私聊界面                \033[0m\n");
    printf("\t\033[5;33;40m*           4.查看聊天记录                \033[0m\n");
    printf("\t\033[5;33;40m*           5.文件传输                   \033[0m\n");
    printf("\t\033[5;33;40m*           6.更改密码                   \033[0m\n");
    printf("\t\033[5;33;40m*           7.在线注销                   \033[0m\n");
    printf("\t\033[5;33;40m*           8.管理员界面                  \033[0m\n");
    printf("\t\033[5;33;40m*           9.退出聊天室 返回登录界面      \033[0m\n");
    printf("\t\033[5;33;40m                                       \033[0m\n");
    printf("\t\033[1;36;40m****************************************\033[0m\n");
    printf("\t------>请输入命令\n");
}

void menu4()//管理员操作界面
{
    system("clear");
    printf("\t\033[1;36;40m*****************网络聊天室***************\033[0m\n");
    printf("\t                                        \n");
    printf("\t\033[5;35;40m        管理员操作:                               \033[0m\n");
    printf("\t\033[5;33;40m*           1.将成员禁言                   \033[0m\n");
    printf("\t\033[5;33;40m*           2.将成员解除禁言                \033[0m\n");
    printf("\t\033[5;33;40m*           3.将成员踢出聊天室                \033[0m\n");
    printf("\t\033[1;36;40m****************************************\033[0m\n");
    printf("\t------>请输入命令\n");
}

int z_socket()//创建数据库,连接服务器
{
    //创建与服务器通信的套接字
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in serveraddr,clientaddr;
   
    //填充服务器
    serveraddr.sin_family=AF_INET;
    serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
    serveraddr.sin_port=htons(8886);
    //memset(serveraddr.sin_zero,0,8);
  
    socklen_t addrlen=sizeof(serveraddr);
    //给服务器发送客户端的链接请求
    if(connect(sockfd,(struct sockaddr *)&serveraddr,addrlen)==-1)
    {
        ERRLOG("connect");
    }
    printf("成功连接上服务器\n");
    //ask_server(sockfd);
    //close(sockfd);
    return 0;
}
void reg(int sockfd)//注册用户
{
    msg.cmd=1;
    printf("\t用户注册:\n");
    printf("\t请输入用户名:\n");
    scanf("%s",myName);
    getchar();
    printf("\t请输入密码:\n");
    scanf("%s",msg.msg);
    getchar();
    printf ("\t管理员/普通用户:0/1 ");
    scanf ("%d", &msg.sig);
    getchar();  
    strcpy(msg.fromname,myName);
    write(sockfd,&msg,sizeof(struct Msg));//向服务器发送注册信息
    read(sockfd,&msg,sizeof(struct Msg));//读取服务器的注册回应
    printf("\t正在校验数据.....\n");
    sleep(1);
    if(msg.cmd==1001)
    {
        printf("\t注册成功!\n\t请稍等.....\n");
    }
    else if(msg.cmd==-5)
    {
        printf("\t注册失败,该用户名已被注册\n");
    }
    else if(msg.cmd==-2)
    {
        printf("\t注册失败,数据库打开失败\n");
    }
    usleep(1500000);
}

void log_in(int sockfd)//登录用户
{
    char password[20];
    //memset(&msg,0,sizeof(msg));
    msg.cmd=2;
    printf("\n\t用户登录:\n");
    printf("\t请输入用户名\n");
    scanf("%s",myName);
    getchar();
    printf("\t请输入密码\n");
    scanf("%s",password);
    getchar();
    strcpy(msg.fromname,myName);
    strcpy(msg.msg,password);
    printf("\n\t正在校验中...\n");
    
    write(sockfd,&msg,sizeof(struct Msg));
    usleep(1500000);
}

void *readMsg(void *p)//用来监听收到的信息
{
    int sockfd=*(int *)p;
    while(1)
    {
        if(flag1==1)//判断线程的退出条件
        {
            flag1=0;//重置线程退出条件
            //pthread_exit(NULL);
        }
        struct Msg msg;
	    memset(&msg, 0, sizeof(msg));
        read(sockfd,&msg,sizeof(msg));
        
        switch(msg.cmd)
        {
            case 8888://查看在线人数
            printf("\n\t当前在线用户:%s\n",msg.msg);
            sleep(3);
            //getchar();
            break;
            case 9001://群聊
            printf("\n\t[群信息]%s : %s \n\t",msg.fromname,msg.msg);
            sprintf(msg1,"[群消息]%s :\n\t%s",msg.fromname,msg.msg);
            //printf("\n\t回车键返回\n ");
            keep_msg(msg1);
            break;
            case 9002://私聊
            printf("\n\t[私信]%s :\n\t%s\n",msg.fromname,msg.msg);
            sprintf(msg2,"[私信]%s向%s发来了一条信息:\n\t%s",msg.fromname,msg.toname,msg.msg);
            keep_msg2(msg2);
            break;
            case 9003://处理发送失败
            printf("\n\t用户不在线或不存在,发送失败\n");
            printf("\n\t回车键返回 \n");
            break;
            case 9008://接收文件
            printf("\n\t%s向%s发来了一个文件:\n\t%s\n",msg.fromname,msg.toname,msg.filename);
            strcpy(msg3,msg.msg);
            Receive(msg3);
            break;
            case 9009://密码修改成功
            printf("\n\t密码修改成功!\n");
            sleep(1);
            break;
            case 9010://密码修改有误
            printf("\n\t密码输入有误,修改失败!\n");
            usleep(1500000);
            break;
            case 9011://收到禁言信号
            printf("\n\t您已被管理员禁言,将无法发送群聊信息\n");
            flag4=1;
            break;
            case 9012://收到解除禁言信号
            printf("\n\t您已被管理员解除禁言\n");
            flag4=0;
            break;
            case 9013://收到踢出信号
            printf("\n\t您已被管理员踢出,即将退出聊天室\n");
            sleep(2);
            exit(1);
            flag1=1;
            break;

        }
        /*if(flag1==1)//判断退出条件
        {
            break;
        }*/
        usleep(400000);
    }
}

void quit_chatroom(int sockfd)//退出聊天室,返回登录界面
{  
    msg.cmd=9;
    strcpy(msg.fromname,myName);
    write(sockfd,&msg,sizeof(struct Msg));
}

void display(int sockfd)//查看当前在线人数
{
    msg.cmd=1;
    write(sockfd,&msg,sizeof(struct Msg));
}

void chat1(int sockfd)//群聊界面
{
    struct Msg msg;
    if(flag4==1)
    {
        printf("\n\t您已被管理员禁言\n");
        return;
    }
    msg.cmd=2;
    strcpy(msg.fromname,myName);
    strcpy(msg.toname,"all");
    printf("\n\t请输入您要发送的内容:\n\t");
    scanf("%s",msg.msg);
    getchar();
    write(sockfd,&msg,sizeof(struct Msg));
    printf("\n\t发送成功,等待处理结果....\n");
}

void chat2(int sockfd)//私聊界面
{
    struct Msg msg;
    msg.cmd=3;
    strcpy(msg.fromname,myName);
    printf("\n\t请输入您要发送的对象:\n\t");
    scanf("%s",msg.toname);
    getchar();
    printf("\t请输入您要发送的内容:\n\t");
    scanf("%s",msg.msg);
    getchar();
    write(sockfd,&msg,sizeof(struct Msg));//向服务器发送请求
    printf("\n\t发送成功,请稍等....\n");
    usleep(500000);

}

void keep_msg(char *msg1)//用来保存收到的群聊记录
{
    //打开数据库
    int ret=sqlite3_open("histroy.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("\t打开数据库失败\n");
        return;
    }
    //往histroy表中添加信息
    char buf[1300];
    memset(buf,0,1300);
    char *errmsg=NULL;
    sprintf(buf,"insert into histroy values('%s','%s')",msg.fromname,msg1);
    ret=sqlite3_exec(database,buf,NULL,NULL,&errmsg);
    /*if(ret!=SQLITE_OK)
    {
        printf("\t数据库操作失败:%s\n",errmsg);
        return;
    }*/
    sqlite3_close(database);
}

void keep_msg2(char *msg2)//用来保存私聊信息
{
    //打开数据库
    int ret=sqlite3_open("histroy.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("\t打开数据库失败\n");
        return;
    }
    //往histroy表中添加信息
    char buf1[1700];
    memset(buf1,0,1700);
    char *errmsg=NULL;
    sprintf(buf1,"insert into histroy1 values('%s','%s','%s')",myName,msg.toname,msg2);
    ret=sqlite3_exec(database,buf1,NULL,NULL,&errmsg);
    if(ret!=SQLITE_OK)
    {
        printf("\t数据库操作失败:%s\n",errmsg);
        return;
    }
    sqlite3_close(database);
}

void dis_history(int sockfd)//查看聊天记录
{
    printf("\n\t a.查看群聊记录\n\t");
    printf("\n\t b.查看个人聊天记录\n\t");
    printf("\n\t=====>请选择: ");
    switch(getchar())
    {
        case 'a':
        chat1_hst();
        break;
        case 'b':
        chat2_hst();
        break;
    }
    printf("\n\t回车键返回 ");
    getchar();
}

void chat1_hst()//打印群聊信息
{
    system("clear");
    printf("\t********网络聊天室***********\n\n\n");
    printf("\t群聊历史记录:                  \n");
    //打开数据库
    int ret=sqlite3_open("histroy.db",&database);
    if(ret!=SQLITE_OK)
    {
        printf("\t打开数据库失败\n");
        return;
    }
    //获取history表中的信息
    char *errmsg=NULL;
    char **result;
    int nrow,ncolumn;//行数,列数
    char *sql="select *from histroy";
    ret=sqlite3_get_table(database,sql,&result,&nrow,&ncolumn,&errmsg);
    if(ret!=SQLITE_OK)
    {
        printf("数据库操作失败%s\n",errmsg);
        return;
    }
    int j;
    for(j=2;j < (nrow+1) * ncolumn;j += 2)
    {
        printf("\n\t%s\n",result[j+1]);
    }
    sqlite3_free_table(result);
    sqlite3_close(database);
}

void chat2_hst()//打印私聊信息
{
    system("clear");
    printf ("\t*************************** 网络聊天室 *****************************\n\n\n");
    printf ("\t私聊历史记录:\n");

    // 打开数据库
    int ret = sqlite3_open("histroy.db", &database);
    if (ret != SQLITE_OK)
    {
        printf ("\t打开数据库失败\n");
        return;
    }

    // 获取histroy表中的信息
    char *errmsg = NULL;
    char **result = NULL;
    int nrow, ncolumn;
    char *sql1 = "select * from histroy1";
    ret = sqlite3_get_table(database, sql1, &result, &nrow, &ncolumn, &errmsg);
    if (ret != SQLITE_OK)
    {
        printf ("数据库操作失败:%s\n", errmsg);
        return;
    }
    int i;
    for (i = 3; i < (nrow+1)*ncolumn; i+=3)
    {
        printf ("\n\t%s\n", result[i+2]);
        /*if(strcmp(result[i], myName) == 0||strcmp(result[i+1],myName) == 0)
        {
            printf ("\n\t%s\n", result[i+2]);
        }*/
    }
    sqlite3_free_table(result);

    // 关闭数据库
    sqlite3_close(database);
}

void change_pass(int sockfd)//修改密码
{
    char ch[2];
    msg.cmd = 6;
    printf ("\n\t您是否确定需要修改密码?(y/n): ");
    fgets(ch, 2, stdin);
    while (getchar()!= '\n');
    if (ch[0] != 'y')
    {
        printf ("\n\t请稍候.....\n");
        usleep(700000);
        return;
    }
    printf ("\t请输入旧密码: ");
    scanf ("%s", msg.msg);
    getchar();
    printf ("\t请输入新密码: ");
    scanf ("%s", msg.filename);
    getchar();
    strcpy (msg.fromname, myName);

    write(sockfd, &msg, sizeof(struct Msg)); // 向服务器发送注册信息

    printf ("\n\t正在校验数据,请稍候......\n");
    sleep(1);
}

void delete_user(int sockfd)// 在线注销
{
    msg.cmd = 7;

    printf ("\n\t正在处理注销操作......\n");
    write (sockfd, &msg, sizeof(struct Msg));  //向服务器发送请求
    printf ("\t注销完成!\n");
    sleep(2);
    //quit_chatroom(sockfd);
    
    //system("clear");

}

void supuser(int sockfd)//管理员权限界面
{
    system("clear");
    printf ("\t\033[1;36;40m*************** 网络聊天室***************\033[0m\n\n\n");
    printf ("\t\033[5;33;40m             1、将成员禁言    \033[0m \n");
    printf ("\t\033[5;33;40m             2、将成员解除禁言    \033[0m \n");
    printf ("\t\033[5;33;40m             3、将成员踢出聊天室     \033[0m\n");
    printf ("\n\t***** 请选择: ");
    char ch[2];
    fgets(ch, 2, stdin);
    while (getchar()!= '\n');
    struct Msg msg;
	memset(&msg, 0, sizeof(msg));
    switch (ch[0])
    {
        case '1':       // 将成员禁言
            silent(sockfd);
            break;
        case '2':       // 将成员解除禁言
            silent_del(sockfd);
            break;          
        case '3':       // 将成员踢出聊天室
            kickout(sockfd);
            break;
    }
    printf ("\n\t回车键返回  ");
    getchar();  
}

void silent(int sockfd)// 将成员禁言
{
    msg.cmd = 9011;
    strcpy (msg.fromname, myName);

    printf ("\n\t请输入您要禁言的用户:\n\t");
    scanf ("%s",msg.toname);
    getchar();

    write (sockfd, &msg, sizeof(struct Msg));  //向服务器发送请求

    printf ("\n\t操作完成,请稍候.....\n");
    usleep (500000);    
}

void silent_del(int sockfd)// 将成员解除禁言
{
    msg.cmd = 9012;
    strcpy (msg.fromname, myName);

    printf ("\n\t请输入您要解除禁言的用户:\n\t");
    scanf ("%s",msg.toname);
    getchar();

    write (sockfd, &msg, sizeof(struct Msg));  //向服务器发送请求

    printf ("\n\t操作完成,请稍候.....\n");
    usleep (500000);        
}

void kickout (int sockfd)// 将成员踢出聊天室
{
    msg.cmd = 9013;
    strcpy (msg.fromname, myName);

    printf ("\n\t请输入您要踢出的用户:\n\t");
    scanf ("%s",msg.toname);
    getchar();

    write (sockfd, &msg, sizeof(struct Msg));  //向服务器发送请求

    printf ("\n\t操作完成,请稍候.....\n");
    usleep (500000);        
}

sent_out.c:

#include"client.h"
extern char myName[20];//保存用户名
extern char msg3[1500];//保存文件内容
void sent_out(int sockfd)//向服务器发送文件
{
    struct Msg msg;
    msg.cmd=5;
    strcpy(msg.fromname,myName);
    printf("\n\t请输入要传输的文件名:\n");
    scanf("%s",msg.filename);
    getchar();
    printf("\n\t请输入要发送的用户:\n");
    scanf("%s",msg.toname);
    getchar();
    int fd=open("./msg.text",O_RDWR|O_CREAT,0664);
    if(fd==-1)
    {
        perror("open");
        return;
    }
    char buf[1023];
    memset(buf,0,1023);
    if(-1==read(fd,buf,1023))
    {
        perror("read");
        return;
    }
    printf("%s\n",buf);
    strcpy(msg.msg,buf);
    write(sockfd,&msg,sizeof(struct Msg));
}


void Receive(char *msg3)//接收文件
{
    printf("%s\n",msg3);
    int fd=open("./1.text",O_WRONLY|O_TRUNC|O_CREAT,0664);
    if(fd==-1)
    {
        perror("open");
        return;
    }
    
    if(-1==write(fd,msg3,1500))
    {
        perror("write");
        return;
    }
    printf("\t您是否现在查看该文件:(Y/N)");
    char ch[2];
    fgets(ch, 2, stdin);
    while (getchar()!= '\n');
    if (ch[0] == 'y')
    {
        printf ("\n\t请稍候.....\n");
        printf("%s\n",msg3);
    }
}

makefile:

run:
	gcc *.c -lpthread -lsqlite3 -o run

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值