聊天室1.0

这聊天室写的很心累,很多地方现在还没有我完善,但是基本功能都有了,也基本了解了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;
}

















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值