聊天室1.0(注册和登录功能)

1、服务器

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sqlite3.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>

#define PORT    9999			//端口号
#define REG     6000			//表示注册请求
#define RES_OK	6001			//成功注册
#define RES_ERR 6002			//注册失败
#define LOGIN   6003			//表示登录请求
#define LOG_OK	6004			//登录成功
#define LOG_ERR 6005			//登录失败
#define SIZE    20              //账号密码的最大长度  

typedef enum {FALSE,TRUE}BOOL;

// 创建,绑定端口和ip,监听套接字
int init();
// 通信套接字
int myAccept(int listen_socket);
//工作函数
void *handl_client(void *v);
//注册
void reg(int cmd,long client_socket);
//登录
BOOL login(int cmd,long client_socket);

int main()
{
	int listen_socket = init();
	if(-1 == listen_socket)
		return -1;
	
	while(1)
	{
		long client_socket = myAccept(listen_socket);
		if(-1 == client_socket)
		{
			continue;
			printf("dasdasdas\n");
		}
		//创建线程
		pthread_t thread;
		pthread_create(&thread,NULL,handl_client,(void *)client_socket);
		
		pthread_detach(thread);
	}
	
	close(listen_socket);
	return 0;
}

// 创建,绑定端口和ip,监听套接字
int init()
{
	int listen_socket = socket(AF_INET, SOCK_STREAM, 0);		//创建
	if(-1 == listen_socket)
	{
		perror("创建套接字失败");
		return -1;
	}
	
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(struct sockaddr_in));
	addr.sin_family      = AF_INET;             /* Internet地址族 */
	addr.sin_port        = htons(PORT);         /* 端口号 */
	addr.sin_addr.s_addr = htonl(INADDR_ANY);   /* IP地址, 绑定本地的所有ip地址*/

	int ret = bind(listen_socket, (const struct sockaddr *)&addr, sizeof(addr));	//绑定
	if(-1 == ret)
	{
		perror("绑定失败");
		return -1;
	}
	
	ret = listen(listen_socket, 5);				// 监听套接字
	if(-1 == ret)
	{
		perror("监听失败");
		return -1;
	}

	return listen_socket;
}

// 通信套接字
int myAccept(int listen_socket)
{
	struct sockaddr_in client_addr;
	socklen_t len = sizeof(client_addr);
	printf("等待用户连接\n");
	int client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, &len);
	if (-1 == client_socket)
	{
		perror("连接失败");
		return -1;
	}
	
	return client_socket;
}

//工作函数,处理客户端请求
void *handl_client(void *v)
{
	long client_socket = (long)v;
	while(1)
	{
		int cmd;
		int ret = read(client_socket,&cmd,sizeof(int));		//判断请求
		if(0 == ret)
		{
			printf("客户端退出\n");
			break;
		}
		
		switch(cmd)
		{
			case REG:								//注册
				reg(cmd,client_socket);
				break;
			case LOGIN:
				login(cmd,client_socket);
				break;
		}
	}
}

//注册模块
void reg(int cmd,long client_socket)
{
	//注册协议:客户端--->服务器
	struct data
	{
		char name[SIZE];		//账号
		char passwd[SIZE];		//密码
	}Data;
	//注册协议:服务器--->客户端
	struct _rep
	{
		int cmd;				//对什么请求反馈
		int result;				//处理结果
	}Rep = {cmd,RES_OK};
	
	sqlite3 *db;
	//打开数据库										
	int ret = sqlite3_open("mydata.db",&db);
	if (ret != SQLITE_OK)
	{
		printf ("数据库打开失败\n");
		Rep.result = RES_ERR;
	}
	char *errmsg;
	//设计数据库内容id,账号,密码
	const char *sql = "create table if not exists mydata(name TEXT,passwd TEXT,primary  key(name))";
	sqlite3_exec(db, sql, NULL, NULL, &errmsg);
	
	//读取客户端的数据部分
	read(client_socket,&Data,sizeof(struct data));	
	
	//不存在,添加进数据库
	char str[100];
	int id = 1;
	sprintf (str, "insert into mydata values('%s','%s')",Data.name,Data.passwd);
	ret = sqlite3_exec(db, str, NULL, NULL, &errmsg );
	if (ret != SQLITE_OK)
	{
		sqlite3_free(errmsg);
		printf("数据已经存在\n");
		Rep.result = RES_ERR;
	}
	
	write(client_socket,&Rep,sizeof(struct _rep));
}

//登录模块
BOOL login(int cmd,long client_socket)
{
	//登录协议:客户端--->服务器
	struct data
	{
		char name[SIZE];		//账号
		char passwd[SIZE];		//密码
	}Data;
	//登录协议:服务器--->客户端
	struct _rep
	{
		int cmd;				//对什么请求反馈
		int result;				//处理结果
	}Rep = {cmd,LOG_ERR};
	
	//打开数据库
	sqlite3 *db;
	int ret = sqlite3_open("mydata.db",&db);
	if (ret != SQLITE_OK)
	{
		printf ("数据库打开失败\n");
		return FALSE;
	}

	//读取客户端的数据部分
	read(client_socket,&Data,sizeof(struct data));	
	
	//进行查找
	char *errmsg;
	const char *sql = "select * from mydata";
	char **value = NULL;
	int row;
	int column;
	ret = sqlite3_get_table(db, sql, &value, &row, &column, &errmsg);
	if (ret != SQLITE_OK)
	{
		printf ("查询失败: %s\n", errmsg);
		sqlite3_free(errmsg);
		Rep.result = LOG_ERR;
		return;
	}
	int i;

	printf("%d\n",row);
	printf("%d\n",column);
	for (i = column; i < (row*column+column); i+=column)
	{
		if(0 == strcmp(value[i],Data.name) && 0 == strcmp(value[i+1],Data.passwd))
		{
			Rep.result = LOG_OK;
			break;
		}
	}
	write(client_socket,&Rep,sizeof(struct _rep));
	
	if(Rep.result == LOG_ERR)
	{
		printf("账号或者密码错误\n");
		return FALSE;
	}
	else if(Rep.result == LOG_OK)
	{
		printf("%s账号登录成功\n",Data.name);
		return TRUE;
	}
}

2、客户端

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sqlite3.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>

#define PORT    9999			//端口号
#define REG     6000			//表示注册请求
#define RES_OK	6001			//成功注册
#define RES_ERR 6002			//注册失败
#define LOGIN   6003			//表示登录请求
#define LOG_OK	6004			//登录成功
#define LOG_ERR 6005			//登录失败
#define SIZE    20              //账号密码的最大长度

typedef enum {FALSE,TRUE}BOOL;

//功能
void func(int conn_socket);
//注册
void Reg(int conn_socket);
//主界面
void menu();
//登录
BOOL Login(int conn_socket);
//在线
void Online(int conn_socket);
//在线界面
void menu_online();

int main()
{
	//创建套接字
	int conn_socket = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == conn_socket)
	{
		perror("创建套接字失败");
		return -1;
	}
	
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(struct sockaddr_in));
	addr.sin_family      = AF_INET;             /* Internet地址族 */
	addr.sin_port        = htons(PORT);         /* 端口号 */
	addr.sin_addr.s_addr = htonl(INADDR_ANY);   /* IP地址, 绑定本地的所有ip地址*/

	//连接客户端
	int ret = connect(conn_socket, (const struct sockaddr *)&addr, sizeof(addr));
	if(-1 == ret)
	{
		perror("绑定失败");
		return -1;
	}
	
	func(conn_socket);
	
	close(conn_socket);
	
	return 0;
}

//主界面
void menu()
{
	printf("1、登录聊天室\n");
	printf("2、注册新账号\n");
	printf("0、退出\n");
}

//功能选择
void func(int conn_socket)
{
	while(1)
	{
		system("clear");
		menu();
		int i;
		scanf("%d",&i);
		
		switch(i)
		{
			case 2:
				Reg(conn_socket);
				break;
			case 1:
				int tmp = Login(conn_socket);
				if(tmp == TRUE)
					Online(conn_socket);
				break;
			case 0:
				printf("程序已经退出\n");
				break;
			default :
				printf("无效指令\n");
				break;
		}	
		if(0 == i)
			break;
	}
}

//注册	
void Reg(int conn_socket)
{
	struct data					
	{
		const int cmd; 
		char name[SIZE];		//账号
		char passwd[SIZE];		//密码
	}Data ={REG};
	
	struct _rep
	{
		int cmd;		//对什么请求反馈
		int result;		//处理结果
	}Rep;
	
	//向服务器发送请求
	printf("请输入注册账户:");
	scanf("%s",Data.name);
	printf("请输入注册密码:");
	scanf("%s",Data.passwd);
	write(conn_socket, &Data, sizeof(struct data));
	//接收服务器反馈信息
	printf("正在等待账号注册\n");
	sleep(1);
	int ret = read(conn_socket, &Rep, sizeof(Rep));
	if (-1 == ret)
	{
		perror ("read error");
	}
	if(Rep.cmd == REG && Rep.result == RES_OK)
	{
		printf("注册成功\n");
	}
	else if(Rep.cmd == REG && Rep.result == RES_ERR)
	{
		printf("账号已经存在,注册失败\n");
	}
}

//登录
BOOL Login(int conn_socket)
{
	//登录协议:客户端--->服务器
	struct data
	{
		const int cmd;
		char name[SIZE];		//账号
		char passwd[SIZE];		//密码
	}Data={LOGIN};
	//登录协议:服务器--->客户端
	struct _rep
	{
		int cmd;				//对什么请求反馈
		int result;				//处理结果
	}Rep;
	
	printf("请输入账号:");
	scanf("%s",Data.name);
	printf("请输入密码:");
	scanf("%s",Data.passwd);
	//向服务器发送请求
	write(conn_socket, &Data, sizeof(struct data));
	//接收服务器反馈信息
	printf("账号登录中....\n");
	sleep(1);
	int ret = read(conn_socket, &Rep, sizeof(Rep));
	if (-1 == ret)
	{
		perror ("read error");
	}
	if(Rep.cmd == LOGIN && Rep.result == LOG_OK)
	{
		system("clear");
		printf("登录成功\n");
		sleep(1);
		return TRUE;
	}
	else if(Rep.cmd == LOGIN && Rep.result == LOG_ERR)
	{
		system("clear");
		printf("账号或密码错误\n");
		sleep(1);
		return FALSE;
	}
}

//在线界面
void menu_online()
{
	printf("1、查看在线用户\n");
	printf("2、进入群聊\n");
	printf("3、进入私聊\n");
	printf("4、查看聊天记录\n");
	printf("5、更改用户密码\n");
	printf("6、在线注销当前用户\n");
	printf("0、退出登录\n");
}

//在线
void Online(int conn_socket)
{
	
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章