这聊天室写的很心累,很多地方现在还没有我完善,但是基本功能都有了,也基本了解了TCP的工作机制,等以后在慢慢改吧。
服务器server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <pthread.h>
#include <sqlite3.h>
#define PORT 6666 //端口号
#define FALSE 0
#define TRUE 1
#define SIZE 1024
#define SMALL_SIZE 20
typedef struct _User
{
char name[SMALL_SIZE]; // 用户名
int socket; // 和用户通信的socket
int flag;
int sig;
}User;
User user[SMALL_SIZE];
typedef struct _MSG
{
char filename[SMALL_SIZE]; //文件名
char file[SIZE]; //文件
char inline_user[SIZE]; //在线用户
char password[SMALL_SIZE]; //密码
char information[SIZE]; //消息内容
char fromname[SMALL_SIZE]; //发送消息的名字
char toname[SMALL_SIZE]; //发送给谁的名字
int socket; //套接字
int cmd; //消息类型
int flag; //标志位 离线为 0 在线为 1
int count;
int sig; // 0代表普通用户 1代表管理员用户 2代表该用户被禁言
}Msg;
int Init_socket()
{
//创建socket (socket)
int sockfd = socket(AF_INET , SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("socket");
return FALSE;
}
//命名套接字,绑定本地IP地址和端口 (bind)
struct sockaddr_in addr;
memset(&addr , 0 ,sizeof(addr));
addr.sin_family = AF_INET; //设置协议族
addr.sin_port = htons(PORT); //设置本地端口 honts作用将二字节主机节序转化为网络节字序
addr.sin_addr.s_addr = htonl(INADDR_ANY); //设置本地任意的IP地址 htonl作用将4字节主机字节序转化为网络字节序
int ret;
ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
if(ret == -1)
{
perror("bind");
return FALSE;
}
//监听套接字 (listen)
// int listen(int sockfd, int backlog);
ret = listen(sockfd , 20); //最多20个客户端
if(ret == -1)
{
perror("listen");
return FALSE;
}
printf("等待客户端连接......\n");
return sockfd;
}
int Accept_socket(int sockfd)
{
struct sockaddr_in client_addr;
int len = sizeof(client_addr);
int client_socket = accept(sockfd , (struct sockaddr *)&client_addr , &len);
if(client_socket == -1)
{
perror("accept");
return FALSE;
}
printf("成功接受到一个客户端: %s\n", inet_ntoa(client_addr.sin_addr));
return client_socket;
}
//创建服务器端的数据库
sqlite3 *create_sqlite()
{
sqlite3* database;
int ret = sqlite3_open("chat.db", &database);
if(ret != SQLITE_OK)
{
perror("sqlite3_open");
return NULL;
}
//printf("数据库打开成功\n");
return database;
}
//把用户名和密码还有套接字保存到数据库
int save_information(Msg* msg)
{
sqlite3 *database = create_sqlite();
char *errmsg = NULL;
char *sql = "create table if not exists user(fromname TEXT, password TEXT, socket INTEGER)";
int ret = sqlite3_exec(database, sql, NULL, NULL, &errmsg);
if(ret != SQLITE_OK)
{
printf("打开表失败\n");
perror("sqlite3_exec");
return FALSE;
}
//printf("打开表成功\n");
char buf[1024] = {0};
sprintf(buf, "insert into user values('%s' ,'%s' , %d)", msg->fromname, msg->password,msg->socket);
ret = sqlite3_exec(database, buf , NULL, NULL, &errmsg);
if(ret != SQLITE_OK)
{
printf("数据插入失败\n");
return FALSE;
}
sqlite3_close(database);
}
//登录检查账号和密码
int check(int client_socket ,Msg *msg)
{
sqlite3 *database = create_sqlite();
//打开表
int ret = sqlite3_open("chat.db", &database);
if (ret != SQLITE_OK)
{
printf ("打开数据库失败\n");
return;
}
//判断账号密码
char *errmsg = NULL;
char **result = NULL;
int nrow, ncolumn;
char *sq1 = "select * from user";
ret = sqlite3_get_table(database, sq1, &result, &nrow, &ncolumn, &errmsg);
if(ret != SQLITE_OK)
{
printf("数据库操作失败\n");
perror("sqlite3_get_table");
return FALSE;
}
int flag1 = 0; //检测账号存不存在
int flag2 = 0; //检测密码真不真却
int i;
for(i = 3; i < (nrow+1)*ncolumn; i += 3)
{
if(strcmp(result[i], msg->fromname) == 0)
{
if(strcmp(result[i+1],msg->password) != 0)
{
flag2 = 1;
}
flag1 = 1;
break;
}
}
if(flag1 != 1)
{
msg->cmd = -3;
printf("账号不存在\n");
write(client_socket, msg, sizeof(struct _MSG));
}
if(flag2 == 1)
{
msg->cmd = -4;
printf("密码错误\n");
write(client_socket, msg, sizeof(struct _MSG));
}
sqlite3_free_table(result);
sqlite3_close(database);
}
//修改密码
int update_password(int client_socket, Msg *msg)
{
printf("%s正在修改密码\n", msg->fromname);
sqlite3 *database = create_sqlite();
char *errmsg = NULL;
char buf[SIZE];
sprintf(buf,"update user set password = '%s' where fromname = '%s'",msg->password,msg->fromname);
int ret = sqlite3_exec(database, buf, NULL, NULL,&errmsg);
if(ret != SQLITE_OK)
{
msg->cmd = -5;
printf("修改密码失败\n");
printf("sqlite3_exec");
write(client_socket, msg, sizeof(struct _MSG));
return FALSE;
}
printf("%s密码修改成功\n", msg->fromname);
write(client_socket, msg, sizeof(struct _MSG));
sqlite3_close(database);
}
//查看当前在线人数
void see_inline(int client_socket,Msg *msg)
{
printf("%s正在查看当前在线人数\n",msg->fromname);
int count = 0;
char buf[SIZE] = {0};
int i;
int len;
memset(msg->inline_user, 0 , SIZE);
for(i = 0; i < 20; i++)
{
if(user[i].socket != 0 && user[i].flag == 1)
{
strcat(buf, user[i].name);
len = strlen(buf);
buf[len] = '|';
count++;
}
}
strcpy(msg->inline_user, buf);
msg->count = count;
write(client_socket, msg, sizeof(struct _MSG));
printf("查看成功\n");
}
int reg(int client_socket, Msg *msg)
{
if(msg->sig == 0)
{
printf("%s 正在注册普通用户\n", msg->fromname);
}
else if(msg->sig == 1)
{
printf("%s 正在注册管理员用户\n", msg->fromname);
}
//将用户进行保存
int i;
for(i = 0;i < 20; i++)
{
if(user[i].socket == 0)
{
strcpy (user[i].name , msg->fromname);
user[i].socket = client_socket;
user[i].flag = msg->flag;
user[i].sig = msg->sig;
msg->socket = client_socket;
break;
}
}
if(i == 20)
{
msg->cmd = -1;
printf("注册失败");
write(client_socket, msg, sizeof(struct _MSG));
return FALSE;
}
else
{
msg->cmd = 101;
}
printf("注册成功\n");
save_information(msg);
write(client_socket, msg, sizeof(struct _MSG));
}
//用户登陆
void log1(int client_socket, Msg* msg)
{
check(client_socket, msg);
int i;
for(i = 0; i < 20; i++)
{
if((user[i].socket != 0) && (strcmp(user[i].name ,msg->fromname) == 0))
{
user[i].flag = msg->flag;
if(user[i].sig == 0)
{
printf("普通用户%s 正在登录\n", msg->fromname);
msg->cmd = 102;
}
else if(user[i].sig == 1)
{
printf("管理员用户%s 正在登录\n", msg->fromname);
msg->cmd = 103;
}
break;
}
}
write(client_socket, msg, sizeof(struct _MSG));
printf("%s登陆成功\n",msg->fromname);
save_information(msg);
}
//用户注销
void out_log(int client_socket, Msg* msg)
{
printf("%s 正在注销登陆\n", msg->fromname);
int i;
for(i = 0; i < 20; i++)
{
if((user[i].socket != 0) && (strcmp(user[i].name ,msg->fromname) == 0))
{
user[i].flag = msg->flag;
break;
}
}
msg->cmd = 1100;
write(client_socket, msg, sizeof(struct _MSG));
printf("%s已注销\n",msg->fromname);
}
//检查用户是否被禁言
int look_sclient(int client_socket, Msg *msg)
{
int i;
for(i = 0; i < 20; i++)
{
if((user[i].socket != 0) && (strcmp(user[i].name , msg->fromname) == 0) && user[i].sig == 2)
{
break;
}
}
//打开数据库
sqlite3 *database = create_sqlite();
char *errmsg = NULL;
char **resultp = NULL;
int nrow, ncolumn;
char *sql = "select * from user";
int ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf ("数据库操作失败\n");
return FALSE;
}
for(i = 5; i < (nrow + 1)*ncolumn; i += 3)
{
//将字符串转化为整形数
if (atoi(resultp[i]) != 0 && atoi(resultp[i]) != client_socket)
{
write(atoi(resultp[i]), msg, sizeof(struct _MSG));
}
}
printf("\n");
sqlite3_free_table(resultp);
// 关闭数据库
sqlite3_close(database);
return TRUE;
}
//群聊
int chat (int client_socket, Msg *msg)
{
printf("%s 发了一条群聊消息\n", msg->fromname);
//打开数据库
sqlite3 *database = create_sqlite();
char *errmsg = NULL;
char **resultp = NULL;
int nrow, ncolumn;
char *sql = "select * from user";
int ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf ("数据库操作失败\n");
return FALSE;
}
int i;
for(i = 5; i < (nrow + 1)*ncolumn; i += 3)
{
//将字符串转化为整形数
if (atoi(resultp[i]) != 0 && atoi(resultp[i]) != client_socket)
{
write(atoi(resultp[i]), msg, sizeof(struct _MSG));
}
}
printf("\n");
sqlite3_free_table(resultp);
// 关闭数据库
sqlite3_close(database);
return TRUE;
}
//私聊
int chat2(int client_socket, Msg* msg)
{
printf("%s 给 %s 发了一条消息\n",msg->fromname,msg->toname);
//打开数据库
sqlite3 *database = create_sqlite();
char *errmsg = NULL;
char **resultp = NULL;
int nrow, ncolumn;
char *sql = "select * from user";
int ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf ("数据库操作失败\n");
return FALSE;
}
int i;
for(i = 5; i < (nrow + 1)*ncolumn; i += 3)
{
//将字符串转化为整形数
if (atoi(resultp[i]) != 0 && strcmp(resultp[i-2], msg->toname) == 0)
{
write(atoi(resultp[i]), msg, sizeof(struct _MSG));
break;
}
}
printf("\n");
sqlite3_free_table(resultp);
// 关闭数据库
sqlite3_close(database);
return TRUE;
}
//文件传输
int file_send(int client_socket, Msg* msg)
{
printf("%s正在向%s传输文件\n", msg->fromname, msg->toname);
//打开数据库
sqlite3 *database = create_sqlite();
char *errmsg = NULL;
char **resultp = NULL;
int nrow, ncolumn;
char *sql = "select * from user";
int ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf ("数据库操作失败\n");
return FALSE;
}
int i;
for(i = 5; i < (nrow + 1)*ncolumn; i += 3)
{
//将字符串转化为整形数
if (atoi(resultp[i]) != 0 && strcmp(resultp[i-2], msg->toname) == 0)
{
msg->cmd = 1030;
write(atoi(resultp[i]), msg, sizeof(struct _MSG));
printf("传输成功\n");
break;
}
}
sqlite3_free_table(resultp);
// 关闭数据库
sqlite3_close(database);
}
int keep_sclient(int client_socket, Msg* msg)
{
printf("管理员%s 正在对用户%s 进行禁言\n", msg->fromname, msg->toname);
int i;
for(i = 0; i < 20; i++)
{
if((user[i].socket != 0) && (strcmp(user[i].name ,msg->toname) == 0))
{
user[i].sig = msg->sig;
}
}
//打开数据库
sqlite3 *database = create_sqlite();
char *errmsg = NULL;
char **resultp = NULL;
int nrow, ncolumn;
char *sql = "select * from user";
int ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf ("数据库操作失败\n");
return FALSE;
}
for(i = 5; i < (nrow + 1)*ncolumn; i += 3)
{
//将字符串转化为整形数
if (atoi(resultp[i]) != 0 && strcmp(resultp[i-2], msg->toname) == 0)
{
msg->cmd = 1040;
write(atoi(resultp[i]), msg, sizeof(struct _MSG));
break;
}
}
printf("\n");
usleep(500000);
printf("禁言成功\n");
sqlite3_free_table(resultp);
// 关闭数据库
sqlite3_close(database);
}
int delete_sclient(int client_socket, Msg* msg)
{
printf("管理员%s 正在对用户%s 解除禁言\n", msg->fromname, msg->toname);
int i;
for(i = 0; i < 20; i++)
{
if((user[i].socket != 0) && (strcmp(user[i].name ,msg->toname) == 0))
{
user[i].sig = msg->sig;
}
}
//打开数据库
sqlite3 *database = create_sqlite();
char *errmsg = NULL;
char **resultp = NULL;
int nrow, ncolumn;
char *sql = "select * from user";
int ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf ("数据库操作失败\n");
return FALSE;
}
for(i = 5; i < (nrow + 1)*ncolumn; i += 3)
{
//将字符串转化为整形数
if (atoi(resultp[i]) != 0 && strcmp(resultp[i-2], msg->toname) == 0)
{
msg->cmd = 1050;
write(atoi(resultp[i]), msg, sizeof(struct _MSG));
break;
}
}
printf("\n");
usleep(500000);
printf("解除禁言成功\n");
sqlite3_free_table(resultp);
// 关闭数据库
sqlite3_close(database);
}
//踢人
int kick_out(int client_socket, Msg* msg)
{
printf("管理员%s 正在将普通用户%s 踢出聊天室\n", msg->fromname, msg->toname);
int i;
for(i = 0; i < 20; i++)
{
if((user[i].socket != 0) && (strcmp(user[i].name ,msg->toname) == 0))
{
user[i].flag = msg->flag;
}
}
//打开数据库
sqlite3 *database = create_sqlite();
char *errmsg = NULL;
char **resultp = NULL;
int nrow, ncolumn;
char *sql = "select * from user";
int ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf ("数据库操作失败\n");
return FALSE;
}
for(i = 5; i < (nrow + 1)*ncolumn; i += 3)
{
//将字符串转化为整形数
if (atoi(resultp[i]) != 0 && strcmp(resultp[i-2], msg->toname) == 0)
{
msg->cmd = 1060;
write(atoi(resultp[i]), msg, sizeof(struct _MSG));
break;
}
}
printf("\n");
usleep(500000);
printf("踢出成功\n");
sqlite3_free_table(resultp);
// 关闭数据库
sqlite3_close(database);
}
void *handle_client(void *v)
{
int client_socket = (int)v;
Msg msg;
while(1)
{
//从客户端读一个结构体
int ret = read(client_socket , &msg , sizeof(msg));
if(ret == -1)
{
perror("read");
break;
}
if(ret == 0)
{
printf("客户端退出\n");
break;
}
switch(msg.cmd)
{
case 1: //客户端进行注册
reg(client_socket , &msg);
break;
case 2:
log1(client_socket, &msg);
break;
case 1001:
chat(client_socket, &msg);
break;
case 1002:
chat2(client_socket, &msg);
break;
case 1005:
update_password(client_socket, &msg);
break;
case 1006:
see_inline(client_socket, &msg);
break;
case 1009:
file_send(client_socket, &msg);
break;
case 1099:
out_log(client_socket, &msg);
break;
case 9001:
keep_sclient(client_socket, &msg);
break;
case 9002:
delete_sclient(client_socket, &msg);
break;
case 9003:
kick_out(client_socket, &msg);
break;
default:
break;
}
}
close(client_socket);
}
int main()
{
int sockfd = Init_socket();
while(1)
{
int client_socket = Accept_socket(sockfd);
pthread_t id;
//创建线程
pthread_create(&id, NULL, handle_client, (void *)client_socket);
//线程分离
pthread_detach(id);
}
close(sockfd);
return 0;
}
客户端client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 6666
#define FALSE 0
#define TRUE 1
#define SIZE 1024
#define SMALL_SIZE 20
typedef struct _MSG
{
char filename[SMALL_SIZE]; //文件名
char file[SIZE]; //文件
char inline_user[SIZE]; //在线用户
char password[SMALL_SIZE]; //密码
char information[SIZE]; //消息内容
char fromname[SMALL_SIZE]; //发送消息的名字
char toname[SMALL_SIZE]; //发送给谁的名字
int socket; //套接字
int cmd; //消息类型
int flag; //标志位 离线为 0 在线为 1
int count; //计算在线人数
int sig; // 0代表普通用户 1代表管理员用户 2代表该用户被禁言
}Msg;
char myname[SMALL_SIZE]; //用户名
int Init_socket()
{
int sockfd = socket(AF_INET , SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("socket");
return FALSE;
}
struct sockaddr_in addr;
memset(&addr , 0 ,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
inet_aton("127.1.1.1", &(addr.sin_addr));
int ret = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
if(ret == -1)
{
perror("connect");
return -1;
}
printf("成功连上服务器\n");
return sockfd;
}
//注册登陆界面
void menu()
{
time_t NOW_TIME;
time(&NOW_TIME);
system("clear");
printf("%s", ctime(&NOW_TIME));
printf("************************************\n");
printf("***1. 注册 *****\n");
printf("***2. 登陆 *****\n");
printf("***3. 退出 *****\n");
printf(" \n");
printf(" BY:NPC\n");
printf("************************************\n");
}
//普通用户功能界面
void user_menu()
{
time_t NOW_TIME;
time(&NOW_TIME);
system("clear");
printf("%s", ctime(&NOW_TIME));
printf("**************普通用户界面***************\n");
printf(" 1 群聊 \n");
printf(" 2 私聊 \n");
printf(" 3 查看当前在线人数 \n");
printf(" 4 查看聊天记录 \n");
printf(" 5 修改密码 \n");
printf(" 6 文件传输 \n");
printf(" 7 注销 \n");
printf(" \n");
printf(" BY:NPC\n");
printf("******************************************\n");
}
//管理员用户功能界面
void supuser_menu()
{
time_t NOW_TIME;
time(&NOW_TIME);
system("clear");
printf("%s", ctime(&NOW_TIME));
printf("******** * *管理员用户界面***************\n");
printf(" 1 群聊 \n");
printf(" 2 私聊 \n");
printf(" 3 查看当前在线人数 \n");
printf(" 4 查看聊天记录 \n");
printf(" 5 修改密码 \n");
printf(" 6 文件传输 \n");
printf(" 7 注销 \n");
printf(" 8 管理员特权页面 \n");
printf(" \n");
printf(" BY:NPC\n");
printf("*****************************************\n");
}
//创建客户端数据库
sqlite3 *create_sqlite()
{
//打开一个表
sqlite3 *database;
int ret = sqlite3_open("history.db", &database);
if(ret != SQLITE_OK)
{
perror("sqlite3_open");
return NULL;
}
return database;
}
//保存信息
int save_chat(Msg *msg)
{
sqlite3 *database = create_sqlite(msg);
char *errmsg = NULL;
char *sql = "create table if not exists chat(fromname TEXT, toname TEXT, information TEXT)";
int ret = sqlite3_exec(database, sql, NULL, NULL, &errmsg);
if(ret != SQLITE_OK)
{
printf("打开表失败\n");
perror("sqlite3_exec");
return FALSE;
}
char buf[SIZE] = {0};
sprintf(buf, "insert into chat values('%s' ,'%s' ,'%s')", msg->fromname, msg->toname, msg->information);
ret = sqlite3_exec(database, buf , NULL, NULL, &errmsg);
if(ret != SQLITE_OK)
{
printf("数据插入失败\n");
return FALSE;
}
sqlite3_close(database);
}
//查看聊天记录
int look_chat()
{
system("clear");
printf("************聊天记录**************\n");
sqlite3 *database = create_sqlite();
int ret = sqlite3_open("history.db", &database);
if(ret != SQLITE_OK)
{
printf("数据库打开失败\n");
return FALSE;
}
int nrow, ncolumn; //行 列
char *errmsg = NULL;
char **result = NULL; //保存数据的数组
char buf[50] = "select * from chat";
ret = sqlite3_get_table(database, buf, &result, &nrow ,&ncolumn, &errmsg);
if(ret != SQLITE_OK)
{
printf("无聊天记录\n");
return FALSE;
}
int i;
for(i = 0;i < (nrow+1)*ncolumn ;i++)
{
if(i % ncolumn == 0)
printf("\n");
printf("%-20s", result[i]);
}
printf("\n");
sqlite3_free_table(result);
sqlite3_close(database);
}
//查看在线用户
void see_inline(int sockfd)
{
Msg msg;
msg.cmd = 1006;
strcpy(msg.fromname , myname);
//向服务器发送请求
write(sockfd , &msg, sizeof(Msg));
}
//查看用户是否被禁言
int look_sclient(int sockfd)
{
Msg msg;
msg.cmd = 1008;
strcpy(msg.fromname , myname);
//向服务器发送请求
write(sockfd , &msg, sizeof(Msg));
}
//群聊
void chat(int sockfd)
{
Msg msg;
msg.cmd = 1001;
strcpy(msg.fromname, myname);
printf("请输入你要发送的群聊消息:\n");
scanf("%s", msg.information);
write(sockfd, &msg, sizeof(Msg));
save_chat(&msg);
}
//私聊
void chat2(int sockfd)
{
Msg msg;
msg.cmd = 1002;
strcpy(msg.fromname, myname);
printf("请输入你要发送的对象的名字:\n");
scanf("%s", msg.toname);
printf("请输入你要发送的内容:\n");
scanf("%s", msg.information);
write(sockfd, &msg, sizeof(Msg));
save_chat(&msg);
}
//修改密码
int change_password(int sockfd)
{
Msg msg;
strcpy(msg.fromname, myname);
msg.cmd = 1005;
char buf[20];
printf("请输入你的旧密码:\n");
scanf("%s" , buf);
getchar();
memset(buf , 0 ,sizeof(buf));
printf("请输入你的新密码:\n");
scanf("%s" , buf);
getchar();
strcpy(msg.password , buf);
write(sockfd , &msg, sizeof(Msg));
printf("正在校验数据信息.........\n");
usleep(500000);
printf("您的密码修改成功\n");
usleep(500000);
}
//文件传输
void file_send(int sockfd)
{
Msg msg;
msg.cmd = 1009;
strcpy (msg.fromname, myname);
printf("请输入传送文件的对象的用户名:\n");
scanf("%s" ,msg.toname);
printf ("当前目录下的文件有: \n");
system ("ls");
printf ("请输入您要传送的文件名: \n");
scanf ("%s", msg.filename);
//打开要读的文件
int fd = open(msg.filename, O_RDONLY);
if (fd == -1)
{
perror ("open");
return;
}
int ret;
while(ret = read(fd , msg.file, SIZE))
{
if (ret == -1)
{
perror("read");
break;
}
write (sockfd, &msg, sizeof(Msg));
printf("文件传输成功\n");
sleep(1);
}
}
//注销
void out_log(int sockfd)
{
Msg msg;
strcpy(msg.fromname, myname);
msg.cmd = 1099;
msg.flag = 0;
write(sockfd, &msg, sizeof(Msg));
}
//禁言
void keep_sclient(int sockfd)
{
Msg msg;
msg.cmd = 9001;
msg.sig = 2;
strcpy(msg.fromname , myname);
//char name[20];
printf("请输入你要禁言的用户名:");
scanf("%s", msg.toname);
write(sockfd , &msg, sizeof(msg));
printf("禁言成功\n");
sleep(1);
}
//解除禁言
void delete_sclient(int sockfd)
{
Msg msg;
msg.cmd = 9002;
msg.sig = 0;
strcpy(msg.fromname , myname);
//char name[20];
printf("请输入你要解除禁言的用户名:");
scanf("%s", msg.toname);
write(sockfd , &msg, sizeof(msg));
printf("解除禁言成功\n");
sleep(1);
}
//踢人出聊天室
void kickout(int sockfd)
{
Msg msg;
msg.cmd = 9003;
msg.flag = 0;
strcpy(msg.fromname , myname);
printf("请输入你要踢出的用户名:");
scanf("%s", msg.toname);
write(sockfd , &msg, sizeof(msg));
}
//管理员权限
void superuser(int sockfd)
{
system("clear");
printf("***************管理员特权******************\n");
printf(" 1. 禁言 \n");
printf(" 2. 解除禁言 \n");
printf(" 3. 踢人出聊天室 \n");
printf("*******************************************\n");
printf("请输入数字:\n");
char ch[2];
scanf("%s", ch);
switch(ch[0])
{
case '1':
keep_sclient(sockfd); //禁言
break;
case '2':
delete_sclient(sockfd); //解除禁言
break;
case '3':
kickout(sockfd); //踢人出聊天室
break;
default:
break;
}
}
//用户使用界面
void User(int sockfd)
{
Msg msg;
while(1)
{
int num;
system("clear");
user_menu();
printf("请输入数字:\n");
scanf("%d", &num);
switch(num)
{
case 1: //群聊
chat(sockfd);
//save_chat(&msg);
break;
case 2: //私聊
chat2(sockfd);
//save_chat(&msg);
break;
case 3:
see_inline(sockfd); //查看当前在线人数
sleep(1);
getchar();
printf("请按回车键返回主菜单\n");
getchar();
break;
case 4:
look_chat(); //查看聊天记录
getchar();
printf("请按回车键返回主菜单\n");
getchar();
break;
case 5:
change_password(sockfd); //修改密码
break;
case 6:
file_send(sockfd); //传输文件
break;
case 7:
out_log(sockfd); //注销登入
sleep(2);
exit(0);
break;
default:
exit(0);
break;
}
}
}
//超级用户使用界面
void Sup_User(int sockfd)
{
Msg msg;
while(1)
{
int num;
system("clear");
supuser_menu();
printf("请输入数字:\n");
scanf("%d", &num);
switch(num)
{
case 1: //群聊
chat(sockfd);
//save_chat(&msg);
break;
case 2: //私聊
chat2(sockfd);
//save_chat(&msg);
break;
case 3:
see_inline(sockfd); //查看当前在线人数
sleep(1);
getchar();
printf("请按回车键返回主菜单\n");
getchar();
break;
case 4:
look_chat(); //查看聊天记录
getchar();
printf("请按回车键返回主菜单\n");
getchar();
break;
case 5:
change_password(sockfd); //修改密码
break;
case 6:
file_send(sockfd); //传输文件
break;
case 7:
out_log(sockfd); //注销登陆
sleep(2);
exit(0);
break;
case 8:
superuser(sockfd); //管理员权限
break;
default:
exit(0);
break;
}
}
}
//用户注册
void reg(int sockfd)
{
Msg msg;
msg.cmd = 1;
msg.flag = 0; //在线为1 不在线为0
printf("***************注册*************\n");
printf(" 1.普通用户 2.管理员用户\n");
printf("请选择:\n");
char ch[2];
scanf("%s", ch);
switch(ch[0])
{
case '1':
{
msg.sig = 0;
printf("*********普通注册***********\n");
printf("请输入用户名: ");
scanf("%s", myname);
strcpy(msg.fromname , myname);
printf("请输入密码: ");
scanf("%s", msg.password);
break;
}
case '2':
{
printf("**********管理员注册***********\n");
msg.sig = 1;
printf("请输入用户名: ");
scanf("%s", myname);
strcpy(msg.fromname , myname);
printf("请输入密码: ");
scanf("%s", msg.password);
break;
}
default:
break;
}
//向服务器发送请求
write(sockfd, &msg, sizeof(msg));
read (sockfd, &msg ,sizeof(msg));
printf("正在校验注册信息......\n");
usleep(500000);
if(msg.cmd == 101)
{
printf("注册成功\n");
usleep(500000);
}
else if(msg.cmd == -1)
{
printf("注册失败\n");
usleep(500000);;
}
}
void *Readmsg(void *v)
{
int sockfd = (int)v;
Msg msg;
while(1)
{
char buf[1024] = {0};
memset(&msg, 0, sizeof(Msg));
read(sockfd , &msg, sizeof(Msg));
switch(msg.cmd)
{
case 1001:
sprintf(buf,"%s发了一条群聊消息: %s",msg.fromname, msg.information);
printf("%s\n", buf);
break;
case 1002:
sprintf(buf,"%s给你发了一句悄悄话:%s", msg.fromname, msg.information);
printf("%s\n", buf);
break;
case 1005:
printf("密码修改成功\n");
break;
case 1006:
system("clear");
printf("*****************聊天室环境***************\n");
printf("当前在线人数为:%d人\n", msg.count);
printf("当前在线的用户名分别为: %s\n", msg.inline_user);
break;
case 1030:
printf("文件传输完成\n");
break;
case 1040:
printf("你已被管理员禁言\n");
break;
case 1050:
printf("你已被管理员解除禁言\n");
break;
case 1060:
printf("你被管理员踢出聊天室\n");
sleep(1);
exit(0);
break;
case 1100:
printf("用户已注销\n");
printf("系统将两秒后退出!\n");
sleep(2);
break;
case -1:
printf("注册失败\n");
break;
case -2:
printf("登陆失败\n");
break;
case -4:
printf("密码错误\n");
break;
case -5:
printf("密码修改失败\n");
break;
case -10:
printf("该用户已离线\n");
break;
default:
break;
}
}
}
//用户登录
int log1(int sockfd)
{
Msg msg;
sqlite3 * database = create_sqlite();
msg.cmd = 2;
msg.flag = 1;
printf("用户登录\n");
printf("请输入你的账号:\n");
scanf("%s", msg.fromname);
printf("请输入你的密码:\n");
scanf("%s", msg.password);
write(sockfd ,&msg ,sizeof(msg));
read(sockfd ,&msg ,sizeof(msg));
if(msg.cmd == 102)
{
printf("正在验证信息,请稍后.....\n");
usleep(500000);
printf("登陆成功\n");
usleep(500000);
//读写分离
pthread_t id;
pthread_create(&id , NULL , Readmsg, (void *)sockfd);
pthread_detach(id);
User(sockfd);
}
else if(msg.cmd == 103)
{
printf("正在验证信息,请稍后.....\n");
usleep(500000);
printf("登陆成功\n");
usleep(500000);
//读写分离
pthread_t id;
pthread_create(&id , NULL , Readmsg, (void *)sockfd);
pthread_detach(id);
Sup_User(sockfd);
}
else if(msg.cmd == -3)
{
printf("账号不存在\n");
sleep(2);
return FALSE;
}
else if(msg.cmd == -4)
{
printf("密码错误\n");
sleep(2);
return FALSE;
}
return TRUE;
}
int ask_server(int sockfd)
{
int num;
while(1)
{
system("clear");
menu();
printf("请选择功能:\n");
scanf("%d", &num);
switch(num)
{
case 1:
{ //注册
reg(sockfd);
break;
}
case 2: //登录
log1(sockfd);
break;
case 3: //退出
exit(0);
break;
default:
break;
}
}
}
int main()
{
int sockfd = Init_socket();
ask_server(sockfd);
close(sockfd);
return 0;
}