聊天室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)
{
	
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章