聊天室跟新(2)

本文详细介绍了一个基于C语言的聊天室系统实现,包括服务器端和客户端的代码设计。服务器负责处理用户注册、登录、私聊、群聊等功能,通过SQLite数据库管理用户信息和聊天记录。客户端则提供用户界面,实现登录、查看在线用户、发送私聊和群聊消息等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、服务器代码

#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>
#include <time.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 LOG_NO  6006			//已经登录了
#define WHISPER 6008		    //表示私聊请求
#define PER_OK	6009			//私聊成功
#define PER_ERR	6010			//用户不存在
#define MYSELF	6011			//用户本身
#define OTHER	6012			//其他用户
#define NUM     6013			//人数
#define SIZE    20              //账号密码的最大长度  
#define EXIT	6014			//登出
#define TALK    6015			//群聊
#define REMOVE  6016			//注销
#define REVEISE	6017			//修改密码
#define OK		6018			//修改成功
#define NO		6019			//修改失败
#define LOOK	6020			//查看记录

typedef enum {FALSE,TRUE}BOOL;

// 创建,绑定端口和ip,监听套接字
int init();
// 通信套接字
int myAccept(int listen_socket);
//创建库
void cerat_k();
//工作函数
void *handl_client(void *v);
//注册
void reg(int cmd,long client_socket);
//登录
BOOL login(int cmd,long client_socket);
//私聊
void whisper(int cmd,long client_socket);
//群聊
void talk(int cmd,long client_socket);
//在线人数
void num(int cmd,long client_socket);
//退出
void leave(int cmd,long client_socket);
//注销
void Remove(int cmd,long client_socket);
//修改密码
void reveise(int cmd,long client_socket);
//查看记录
void Look_my(int cmd,long client_socket);

int count;			//在线人数

int main()
{
	cerat_k();
	int listen_socket = init();
	if(-1 == listen_socket)
		return -1;
	
	while(1)
	{
		long client_socket = myAccept(listen_socket);
		if(-1 == client_socket)
		{
			continue;
		}
		//创建线程
		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;
	}
	printf ("连接成功\n");
	printf ("客户端的 ip = %s, 端口 = %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
	return client_socket;
}

//创建库
void cerat_k()
{
	//创建信息数据库
	sqlite3 *db1;										
	int ret = sqlite3_open("mydata.db",&db1);
	if (ret != SQLITE_OK)
	{
		printf ("mydata数据库打开失败\n");
	}
	char *errmsg;
	const char *sql = "create table if not exists mydata(name TEXT,passwd TEXT,primary  key(name))";
	sqlite3_exec(db1, sql, NULL, NULL, &errmsg);
	
	//创建在线数据库	
	sqlite3 *db2;	
	ret = sqlite3_open("online.db",&db2);
	if (ret != SQLITE_OK)
	{
		printf ("onlinr数据库打开失败\n");
	}
	const char *sq2 = "create table if not exists online(name TEXT,socket INTEGER,primary  key(name))";
	sqlite3_exec(db2, sq2, NULL, NULL, &errmsg);
	
	//创建聊天库	
	sqlite3 *db3;	
	ret = sqlite3_open("chat.db",&db3);
	if (ret != SQLITE_OK)
	{
		printf ("chat数据库打开失败\n");
	}
	const char *sq3 = "create table if not exists chat(ID INTEGER,sendname TEXT,content TEXT,recename TEXT,primary  key(ID))";
	sqlite3_exec(db3, sq3, NULL, NULL, &errmsg);
	
	//防止服务器意外退出
	char buf[100];
	sprintf(buf ,"delete from online");
	ret = sqlite3_exec(db2, buf, NULL, NULL, &errmsg );
	if(ret != SQLITE_OK)
	{
		printf ("%s\n",errmsg);
	}	
	
	sqlite3_close( db1 );
	sqlite3_close( db2 );
	sqlite3_close( db3 );
}

//工作函数,处理客户端请求
void *handl_client(void *v)
{
	long client_socket = (long)v;
	int tmp = FALSE;
	while(1)
	{
		int cmd;
		int ret = read(client_socket,&cmd,sizeof(int));		//判断请求
		if(0 == ret)
		{
			printf("客户端退出\n");
			break;
		}
		
		switch(cmd)
		{
			case REG:								//注册
				printf("请求注册\n");
				reg(cmd,client_socket);
				break;
			case LOGIN:								//登录
				printf("请求登录\n");
				tmp = login(cmd,client_socket);
				break;
			case WHISPER :							//私聊
				if(tmp == TRUE)
				{
					printf("进入私聊\n");
					whisper(cmd,client_socket);
				}
				break;
			case NUM:								//在线人数
				if(tmp == TRUE)
				{
					printf("查看当前人数\n");
					num(cmd,client_socket);
				}
				break;
			case EXIT:								//下线
				if(tmp == TRUE)
				{
					printf("请求下线\n");
					leave(cmd,client_socket);
				}
				break;
			case TALK:								//群聊
				if(tmp == TRUE)
				{
					printf("进入群聊\n");
					talk(cmd,client_socket);
				}
				break;
			case REMOVE:
				if(tmp == TRUE)
				{
					printf("注销\n");
					Remove(cmd,client_socket);
				}
				break;
			case REVEISE:
				if(tmp == TRUE)
				{
					printf("修改密码\n");
					reveise(cmd,client_socket);
				}
				break;
			case LOOK:
				if(tmp == TRUE)
				{
					printf("查找记录\n");
					Look_my(cmd,client_socket);
				}
		}
	}
}

//注册模块
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;
	}
	
	//读取客户端的数据部分
	read(client_socket,&Data,sizeof(struct data));	
	
	//不存在,添加进数据库
	char *errmsg;
	char str[100];
	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;
	}
	else
		printf("注册成功,账号为:%s,密码为%s\n",Data.name,Data.passwd);
	write(client_socket,&Rep,sizeof(struct _rep));
	sqlite3_close( db );
}

//登录模块
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;

	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;
		}
	}
	
	if(Rep.result == LOG_ERR)
	{
		write(client_socket,&Rep,sizeof(struct _rep));
		printf("账号或者密码错误\n");
		return FALSE;
	}
	else if(Rep.result == LOG_OK)
	{
		//打开数据库	
		sqlite3 *db2;		
		int ret = sqlite3_open("online.db",&db2);
		if (ret != SQLITE_OK)
		{
			printf ("数据库打开失败\n");
			Rep.result = LOG_ERR;;
		}
		
		//添加在线用户
		char str[100];
		sprintf (str, "insert into online values('%s',%ld)",Data.name,client_socket);
		ret = sqlite3_exec(db2, str, NULL, NULL, &errmsg );
		if (ret != SQLITE_OK)
		{
			sqlite3_free(errmsg);
			Rep.result = LOG_NO;
			printf("%s账号已经登录\n",Data.name);
			write(client_socket,&Rep,sizeof(struct _rep));
			sqlite3_close( db2 );
			sqlite3_close( db );
			return FALSE;
		}
		
		write(client_socket,&Rep,sizeof(struct _rep));
		printf("%s账号登录成功\n",Data.name);
		count++;
		sqlite3_close( db2 );
		sqlite3_close( db );
		return TRUE;
	}
}

//私聊
void whisper(int cmd,long client_socket)
{
	//私聊协议:客户端--->服务器
	struct data
	{
		char from_name[SIZE];	//发送方
		char content[1024];		//发送内容
		char to_name[SIZE];		//对象
	}Data;
	//私聊协议:服务器--->客户端
	//给接收方的协议
	struct content
	{
		int cmd;				//对什么请求反馈
		char content[1024];		//接收内容
		int result;				//处理结果
		char name[SIZE];		//发送人名字
	};
	
	struct content CON;
	CON.cmd = cmd;
	CON.result = PER_ERR;
	
	//读取客户端的数据部分
	read(client_socket,&Data,sizeof(struct data));	
	
	//打开在线数据库
	sqlite3 *db;
	int ret = sqlite3_open("online.db",&db);
	if (ret != SQLITE_OK)
	{
		printf ("数据库打开失败\n");
	}
	
	//进行查找
	char *errmsg;
	const char *sql = "select * from online";
	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);
		write(client_socket,&CON,sizeof(struct content)); 
		return;
	}
	
	int i;
	for (i = column; i < (row*column+column); i+=column)
	{		
		if(0 == strcmp(value[i],Data.to_name))				//查看对方是否在线
		{
			if(atol(value[i+1]) == client_socket)		//查看是否是自己
			{
				printf("value[i+1] = %d\n",atoi(value[i+1]));
				printf("client_socket = %ld\n",client_socket);
				printf("给自己发送信息\n");
				break;
			}
			//打开记录数据库
			sqlite3 *db;
			int ret = sqlite3_open("chat.db",&db);
			if (ret != SQLITE_OK)
			{
				printf ("数据库打开失败\n");
			}
			//添加数据
			char *errmsg;
			char str[100];
			sprintf (str, "insert into chat values(NULL,'%s','%s','%s')",Data.from_name,Data.content,Data.to_name);
			ret = sqlite3_exec(db, str, NULL, NULL, &errmsg );
			if (ret != SQLITE_OK)
			{
				sqlite3_free(errmsg);
			}
			
			printf("name = %s\n",Data.from_name);
			strcpy(CON.name,Data.from_name);
			strcpy(CON.content,Data.content);			//获取接收信息
			CON.result = OTHER;
			write(atoi(value[i+1]),&CON,sizeof(struct content));
			printf("%s给%s发送一条信息:\n",CON.name,Data.to_name);	
			printf("%s\n",CON.content);
			CON.result = PER_OK;
			break;
		}
	}
 	write(client_socket,&CON,sizeof(struct content)); 
	sqlite3_close( db );
}

//群聊
void talk(int cmd,long client_socket)
{
	//群聊协议:客户端--->服务器
	struct data
	{
		char name[SIZE];
		char content[1024];		//发送内容
	}Data;
	//群聊协议:服务器--->客户端
	//给接收方的协议
	struct content
	{
		int cmd;				//对什么请求反馈
		char name[SIZE];	
		char content[1024];		//接收内容
		int result;				//结果
	}CON = {cmd};
	
	
	//读取客户端的数据部分
	read(client_socket,&Data,sizeof(struct data));	
	
	//打开数据库
	sqlite3 *db;
	int ret = sqlite3_open("online.db",&db);
	if (ret != SQLITE_OK)
	{
		printf ("数据库打开失败\n");
	}
	
	//进行查找
	char *errmsg;
	const char *sql = "select * from online";
	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);
		write(client_socket,&CON,sizeof(struct content)); 
		return;
	}
	
	int i;
	for (i = column; i < (row*column+column); i+=column)
	{
			if(0 == strcmp(value[i],Data.name))
			{
				CON.result = MYSELF;
				write(client_socket,&CON,sizeof(struct content));
			}
			else
			{
				
			//打开记录数据库
			sqlite3 *db;
			int ret = sqlite3_open("chat.db",&db);
			if (ret != SQLITE_OK)
			{
				printf ("数据库打开失败\n");
			}
			//添加数据
			char *errmsg;
			char str[100];
			sprintf (str, "insert into chat values(NULL,'%s','%s','ALL')",Data.name,Data.content);
			ret = sqlite3_exec(db, str, NULL, NULL, &errmsg );
			if (ret != SQLITE_OK)
			{
				sqlite3_free(errmsg);
			}
				
				CON.result = OTHER;
				strcpy(CON.name,Data.name);
				strcpy(CON.content,Data.content);
				write(atoi(value[i+1]),&CON,sizeof(struct content));
			}
			sqlite3_close( db );
	}
	printf("%s群发了一条信息:%s\n",CON.name,CON.content);
	sqlite3_close( db );
}

//在线人数
void num(int cmd,long client_socket)
{
	printf("--------------\n");
	//服务器--->客户端协议
	struct number
	{
		int cmd;
		int count;			//在线人数
	}Num = {NUM,count};	
	printf("查看在线用户:%d\n",Num.count);
	write(client_socket,&Num,sizeof(struct number));
}

//登出
void leave(int cmd,long client_socket)
{	
	struct _leave
	{
		char name[SIZE];
	}Leave;

	read(client_socket,&Leave,sizeof(struct _leave));
	printf("%s\n",Leave.name);
	
	sqlite3 *db;
	int ret = sqlite3_open("online.db",&db);
	if (ret != SQLITE_OK)
	{
		printf ("数据库打开失败\n");
	}
	//进行登出
	char *errmsg;
	char buf[100];
	sprintf(buf ,"delete from online where name = '%s'",Leave.name);
	ret = sqlite3_exec(db, buf, NULL, NULL, &errmsg );
	if(ret != SQLITE_OK)
	{
		printf ("%s\n",errmsg);
	}	
	count--;
 	write(client_socket,&cmd,sizeof(cmd)); 
	sqlite3_close( db );
}

//注销
void Remove(int cmd,long client_socket)
{
	struct _remove
	{
		char name[SIZE];
	}REmove;
	
	read(client_socket,&REmove,sizeof(struct _remove));
	
	sqlite3 *db;
	int ret = sqlite3_open("mydata.db",&db);
	if (ret != SQLITE_OK)
	{
		printf ("数据库打开失败\n");
	}
	//进行查找
	char *errmsg;
	char buf[100];
	sprintf(buf ,"delete from mydata where name = '%s'",REmove.name);
	ret = sqlite3_exec(db, buf, NULL, NULL, &errmsg );
	if(ret != SQLITE_OK)
	{
		printf ("%s\n",errmsg);
	}	
	count--;
	
	sqlite3 *db1;
	ret = sqlite3_open("chat.db",&db1);
	if (ret != SQLITE_OK)
	{
		printf ("数据库打开失败\n");
	}
	sprintf(buf ,"delete from chat where sendname = '%s'",REmove.name);
	ret = sqlite3_exec(db1, buf, NULL, NULL, &errmsg );
	if(ret != SQLITE_OK)
	{
		printf ("%s\n",errmsg);
	}	
	
 	write(client_socket,&cmd,sizeof(cmd)); 
	
	sqlite3_close( db );
	sqlite3_close( db1 );
}

//修改密码
void reveise(int cmd,long client_socket)
{
	//客户端--->服务器
	struct _rev
	{
		char name[SIZE];
		char old_passwd[SIZE];
		char new_passwd[SIZE];
	}REV;
	
	//服务器--->客户端协议
	struct _rev_to
	{
		int cmd;
		int result;
	}TO = {REVEISE,NO};
	
	read(client_socket,&REV,sizeof(struct _rev));
	sqlite3 *db;
	int ret = sqlite3_open("mydata.db",&db);
	if (ret != SQLITE_OK)
	{
		printf ("数据库打开失败\n");
	}
	//进行修改
	char *errmsg;
	char buf[100];
	sprintf(buf,"update mydata set passwd = '%s' where Name = '%s' and passwd = '%s';",REV.new_passwd,REV.name,REV.old_passwd);
	ret = sqlite3_exec(db, buf, NULL, NULL, &errmsg );
	if(ret != SQLITE_OK)
	{
		printf ("%s\n",errmsg);
	}	
	
	//进行查找
	const char *sq2 = "select * from mydata";
	char **value = NULL;
	int row;
	int column;
	ret = sqlite3_get_table(db, sq2, &value, &row, &column, &errmsg);
	if (ret != SQLITE_OK)
	{
		printf ("查询失败: %s\n", errmsg);
		sqlite3_free(errmsg);
		return;
	}
	int i;
	for (i = column; i < (row*column+column); i+=column)
	{
			if(0 == strcmp(value[i+1],REV.new_passwd))
			{
				TO.result = OK;
				break;
			}
	}
	
	if(TO.result == OK)
	{
		printf("%s修改密码成功\n",REV.name);
	}
	else if(TO.result == NO)
	{
		printf("修改密码失败\n");
	}
	write(client_socket,&TO,sizeof(struct _rev_to)); 
	sqlite3_close( db );
}

//查看记录
void Look_my(int cmd,long client_socket)
{
	//客户端--->服务器
	struct _look
	{
		char name[SIZE];
	}Look;
	//服务器--->客户端
	struct look_
	{
		int cmd;
		char content[SIZE];
		char to_name[SIZE];
	}Look_ = {cmd};
	
	read(client_socket,&Look,sizeof(struct _look));
	
	//打开数据库
	sqlite3 *db;
	int ret = sqlite3_open("chat.db",&db);
	if (ret != SQLITE_OK)
	{
		printf ("数据库打开失败\n");
	}
	
	//进行查找
	char *errmsg;
	const char *sql = "select * from chat";
	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); 
		return;
	}
	
	int i;
	for (i = column; i < (row*column+column); i+=column)
	{
		printf("%s\n",value[i+1]);
		printf("%s\n",Look.name);
		if(0 == strcmp(value[i+1],Look.name))
		{
			strcpy(Look_.content,value[i+2]);
			strcpy(Look_.to_name,value[i+3]);
			printf("%s\n",Look_.content);
			printf("%s\n",Look_.to_name);
			write(client_socket,&Look_,sizeof(struct look_)); 
		}
	}
	sqlite3_close( db );
}

二、客户端代码

#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>
#include <netinet/in.h>
#include <time.h>
#include <stddef.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 LOG_NO  6006			//已经登录了
#define WHISPER 6008		    //表示私聊请求
#define PER_OK	6009			//私聊成功
#define PER_ERR	6010			//用户不存在
#define MYSELF	6011			//用户本身
#define OTHER	6012			//其他用户
#define NUM     6013			//人数
#define SIZE    20              //账号密码的最大长度  
#define EXIT	6014			//登出
#define TALK    6015			//群聊
#define REMOVE  6016			//注销
#define REVEISE	6017			//修改密码
#define OK		6018			//修改成功
#define NO		6019			//修改失败
#define LOOK	6020			//查看记录

typedef enum {FALSE,TRUE}BOOL;

int tmp;			//在线为1,不在线为0
char my_name[SIZE];				//本机账号

//功能
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();
//私聊
void whisper(int conn_socket);
//群聊
void talk(int conn_socket);
//接收消息
void *ReadALL1(void *v);
void *ReadALL2(void *v);
//在线人数
void num(int conn_socket);
//登出
void leave(int conn_socket);
//注销
void Remove(int conn_socket);
//修改密码
void reveise(int conn_socket);
//查看记录
void Look_my(int conn_socket);
//时间记录
void Time()
{ 
	time_t timer;				//time_t就是long int 类型
	struct tm* tblock;
	timer = time(&timer);			//这一句也可以改成time(&timer);
	tblock = localtime(&timer);
	printf("time is: %s\n",asctime(tblock));	
}


//main函数
int main(int argc,char **argv)
{
	//创建套接字
	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(atoi(argv[2]));         /* 端口号 */
	addr.sin_addr.s_addr = inet_addr(argv[1]);   /* 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("--------------------------------\n");
	printf("\t1、登录聊天室\n");
	printf("\t2、注册新账号\n");
	printf("\t0、退出\n");
	printf("------------------------------\n");
}

//功能选择
void func(int conn_socket)
{
	int tmp = FALSE;
	while(1)
	{
		system("clear");
		menu();
		int i;
		scanf("%d",&i);
		switch(i)
		{
			case 2:
				Reg(conn_socket);
				break;
			case 1:
				tmp = Login(conn_socket);
				if(tmp == TRUE)
					Online(conn_socket);
				break;
			case 0:
				if(0 == i)
				system("clear");
				printf("程序已经退出\n");
				sleep(1);
				return;
				break;
			default :
				printf("无效指令\n");
				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));
	//接收服务器反馈信息
	system("clear");
	printf("\t\t正在等待账号注册...\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)
	{
		system("clear");
		printf("\t\t注册成功\n");
		sleep(1);
	}
	else if(Rep.cmd == REG && Rep.result == RES_ERR)
	{
		system("clear");
		printf("\t\t账号已经存在,注册失败\n");
		sleep(1);
	}
}

//登录
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));
	//接收服务器反馈信息
	system("clear");
	printf("\t\t账号登录中....\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");
		strcpy(my_name,Data.name);
		tmp = 1;
		printf("\t\t登录成功\n");
		sleep(1);
		return TRUE;
	}
	else if(Rep.cmd == LOGIN && Rep.result == LOG_ERR)
	{
		system("clear");
		printf("\t\t账号或密码错误\n");
		sleep(1);
		return FALSE;
	}
	else if(Rep.cmd == LOGIN && Rep.result == LOG_NO)
	{
		system("clear");
		printf("\t\t账号已经在线\n");
		sleep(1);
		return FALSE;
	}
}

//在线界面
void menu_online()
{
	printf("--------------------------------\n");
	Time();
	printf("\t1、查看在线用户\n");
	printf("\t2、进入群聊\n");
	printf("\t3、进入私聊\n");
	printf("\t4、查看聊天记录\n");
	printf("\t5、更改用户密码\n");
	printf("\t6、在线注销当前用户\n");
	printf("\t7、修改个性签名\n");
	printf("\t8、发送文件\n");
	printf("\t0、退出登录\n");
	printf("--------------------------------\n");
}

//在线选择
void Online(int conn_socket)
{
	long conn_socket1 = (long)conn_socket;
	
	pthread_t thread2;
	pthread_create(&thread2,NULL,ReadALL2,(void *)conn_socket1);
	pthread_detach(thread2);
	
	while(1)
	{
		system("clear");
		int i;
		menu_online();
		printf("选择功能\n");
		scanf("%d",&i);
		switch(i)
		{
			case 3:
				whisper(conn_socket);
				break;
			case 1:
				num(conn_socket);
				break;
			case 0:
		 		leave(conn_socket);
				printf("%d\n",tmp);
				if(tmp == FALSE)
				{
					return;
				} 
				break;
			case 2:
				talk(conn_socket);
				break;
			case 6: 
				Remove(conn_socket);
				leave(conn_socket);
				if(tmp == FALSE)
				{
					return;
				} 
				break;
			case 5:
				reveise(conn_socket);
				sleep(1);
 				if(tmp == FALSE)
				{
					return;
				} 
				break;
			case 4:
				Look_my(conn_socket);
				break;
		}
	}
}

//私聊
void whisper(int conn_socket)
{
	//私聊协议:客户端--->服务器
	struct data
	{
		int cmd;
		char from_name[SIZE];
		char content[1024];		//发送内容
		char to_name[SIZE];		//对象
	};
	
	struct data Data;
	Data.cmd = WHISPER;
	strcpy(Data.from_name,my_name);
	
	printf("输入聊天对象 :");
	scanf("%s",Data.to_name);
	printf("输入聊天内容 :");
	scanf("%s",Data.content);
	
	write(conn_socket,&Data,sizeof(struct data));
}

//群聊
void talk(int conn_socket)
{
	//群聊协议:客户端--->服务器
	struct data
	{
		int cmd;
		char name[SIZE];
		char content[1024];		//发送内容
	};
	
	struct data Data;
	Data.cmd = TALK;
	strcpy(Data.name,my_name);
	
	printf("输入聊天内容 :");
	scanf("%s",Data.content);
	
	write(conn_socket,&Data,sizeof(struct data));
}

//在线人数
void num(int conn_socket)
{
	int cmd = NUM;
	write(conn_socket,&cmd,sizeof(int));
	printf("正在查看人数\n");
	sleep(1);
}

//下线
void leave(int conn_socket)
{
	
	struct _leave
	{
		int cmd;
		char name[SIZE];
	};
	struct _leave Leave;
	Leave.cmd = EXIT;
	strcpy(Leave.name,my_name);
	
	write(conn_socket,&Leave,sizeof(struct _leave));
	printf("正在下线中...\n");
	sleep(1);
}

//注销
void Remove(int conn_socket)
{
	struct _remove
	{
		int cmd;
		char name[SIZE];
	};
	struct _remove REmove;
	REmove.cmd = REMOVE;
	strcpy(REmove.name,my_name);
	
	write(conn_socket,&REmove,sizeof(struct _remove));
	printf("正在注销中...\n");
}

//修改密码
void reveise(int conn_socket)
{
	struct _rev
	{
		int cmd;
		char name[SIZE];
		char old_passwd[SIZE];
		char new_passwd[SIZE];
	};
	
	struct _rev REV;
	REV.cmd = REVEISE;
	strcpy(REV.name,my_name);
	
	printf("请输入原密码:");
	scanf("%s",REV.old_passwd);
	printf("请输入新密码:");
	scanf("%s",REV.new_passwd);
	write(conn_socket,&REV,sizeof(struct _rev));
	printf("正在修改...\n");
}

//查看记录
void Look_my(int conn_socket)
{
	struct _look
	{
		int cmd;
		char name[SIZE];
	};
	struct _look Look;
	Look.cmd = LOOK;
	strcpy(Look.name,my_name);
	printf("%s\n",Look.name);
	write(conn_socket,&Look,sizeof(struct _look));
}

//读数据----在线人数和下线
void *ReadALL2(void *v)
{
	int cmd;				//对什么请求反馈
	int result;		//结果
	//私聊协议:服务器--->客户端
	struct content
	{
		char content[1024];		//接收内容
		int result;				//处理结果
		char name[SIZE];		//发送人名字
	}CON;
	//在线人数:服务器--->客户端协议
	struct number
	{
		int count;			//在线人数
	}Num;
	//群聊:服务器--->客户端
	struct talking
	{
		char name[SIZE];
		char content[1024];		//接收内容
		int result;				//结果
	}talk_all;
	//查看记录
	struct look_
	{
		char content[SIZE];
		char to_name[SIZE];
	}Look_;
	
	long conn_socket = (long)v;

	while(1)
	{
		int cmd;
		int ret = read(conn_socket,&cmd,sizeof(int));		//判断请求
		switch(cmd)
		{
			case WHISPER :     			//私聊
				ret = read(conn_socket,&CON,sizeof(struct content));
				if(CON.result == PER_OK)
				{
					printf("发送消息成功\n");
					sleep(1);
				}
				else if(CON.result == PER_ERR)
				{
					printf("发送消息失败\n");
					sleep(1);
				}
				else if(CON.result == OTHER)
				{
					printf("%s给你发送一条信息:\n",CON.name);	
					printf("%s\n",CON.content);	
					sleep(1);
				} 	
				break;
			case NUM:
				ret = read(conn_socket,&Num,sizeof(struct number));
				printf("当前有%d人在线\n",Num.count);
				sleep(1);
				break;
			case EXIT:
				tmp = 0;
				printf("tmp = %d\n",tmp);
				printf("下线成功\n");
				sleep(1);
				pthread_exit(NULL);
				break;
			case TALK:
				ret = read(conn_socket,&talk_all,sizeof(struct talking));
				if(talk_all.result == MYSELF)
				{
					printf("发送成功\n");
				}
				else if(talk_all.result == OTHER)
				{
					printf("%s群发:%s\n",talk_all.name,talk_all.content);	 
				}
				break;
			case REMOVE :
				tmp = 0;
				printf("注销成功\n");
				sleep(1);
				break;
			case REVEISE:
				ret = read(conn_socket,&result,sizeof(int));
				if(result == OK)
				{
					tmp = 0;
					printf("修改密码成功\n");
					leave(conn_socket);
				}
				else if(result == NO)
				{
					printf("密码错误,修改密码失败\n");
				}
				break;
			case LOOK:
				ret = read(conn_socket,&Look_,sizeof(struct look_));
				printf("%s向%s发送信息为:%s\n",my_name,Look_.to_name,Look_.content);
				break;
		}
	}
} 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值