一:项目功能介绍
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