第一版聊天室


总结遇到的问题:

在一开始构思架构的时候,肯定是采用CS架构,即客户端与服务器架构。
如何通信是我遇到的第一个问题,开始想用IP地址来确定一个client,通过ip来通信,很快被我否定,因为一个ip可以登录多个client,相同ip会冲突,然后我想到通过客户端与服务器建立的套接字来锁定client,这个也是正确的想法。
接下里是搭建服务器,用数据库来保存信息,很多信息,及时添加。服务器用一个while(1)死循环,accept客户端连接请求,创建一个线程来执行客户端的需求操作。在线程里接收客户端发送的数据,通过flag位来相应处理;
客户端首先是建立与服务器的连接。然后执行登录的操作,由客户端发送登录的一系列的请求,可以登录,可以注册,可以忘记密码等等。在登录函数中,接收服务器发送的flag,判断一系列的操作是否成功。
写到这里,又有了一个很大的问题:一开始,在客户端中,我连续写了两个send,并且都是发送1024个字节,发送账号和密码,在服务器中的登录函数,我连续写了两个recv函数,接收账号和密码,都是接收1024个字节,这时候遇到问题了,第一个send成功了,第二个send,却失败了,服务器没有接收到正确的密码,导致我花了很久来找错误。我百度了,发现是发送接收缓冲区的问题,意思是,在发送和接收存在一个缓冲区,只有当缓冲区里的数据都被读取或者接收完,才会读取或接收下一个指令。我不理解的地方在于我设置的的确是1024,并且都相同。
在写下这个博客之前,我没有再写一个简单的cs架构去验证,是我个人的一个不严谨的地方。
后来我想到了还有许多的flag位,还有许多信息,如果一一对应的发送接收,会很复杂,并且容易出错,然后我想到了用结构体来解决这个问题,通过结构体把所有的信息放在一起发送,简单了许多。我直接百度了怎么发送结构体,需要用memcpy函数,不过后来,朋友告诉我,可以直接发送结构体,我有点石乐志,又是因为自己没有进行尝试,最起码复杂度提高了三分之一。
简单的登录注册写完,接下来就是聊天室了。
我第一想到的是父子进程。当然是客户端。
子进程负责接收服务器发来的消息,通过flag位来判断功能。父进程负责聊天室的功能,比如私聊群聊等。这个很好写。在进入私聊群聊时,我预留了一个地方,写在线成员函数,先不说。
客户端1:私聊进入,首先是在线成员,然后选择私聊对象,然后输入message,然后发送给服务器。
服务器:接收消息,发现是私聊,然后从数据库中查询私聊对象的套接字,然后发送给对象。
客户端2:子进程接收消息,打印消息。

不是很难,主要的问题是接收和发送字节要统一。然后界面上跟随着调试,再进行修改。

群聊与私聊类似,不过我做了一些改变,比如服务器接受群聊消息,然后从数据库中查询在线人员,然后发送给在线的人,客户端接收的 时候进行判断,是否来自自己本身。这就是群聊的一点点不同的地方。

本地聊天记录还没有写。

上面所说的一个在线成员函数是我遇到的比较麻烦的问题了。个人在指针上的操作还不是那么厉害,一开始我再结构体中加入了指针数组,用来存放在线人员的账号,然后发送给客户端,客户端在打印出来,理论上来说,*member[100];是可行的,但是我遇到了问题,打印不出来,是空的,反复调试了许多遍,都没有解决,然后我便采用了二维数组来存放,其实是一个意思,但我不是很明白为什么指针会有问题。(回头重新写一遍的时候再采用这种方法调试)。

第一版就这样结束了。。。功能还不全面,等待第二版。

client.c
#include <stdlib.h> 
#include <stdio.h> 
#include <errno.h> 
#include <string.h> 
#include <netdb.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#include <string.h>

#define portnumber 1234
#define ERROR 1
#define SUCCESS 0

#include <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sqlite3.h>
#include <math.h>

#define DATA "/home/wechat/server/data.db"
#define LEN sizeof(struct message)

static char zhanghao[20];

struct user
{
	char zhanghao[20];
	char mima[20];
	char change_mima[20];
	char mibao[20];
	char mibao_daan[20];
	int flag;    //0、error.1、success
};

struct message
{
	int flag;				//1、siliao.2、qubliao
	int len;
	char send[20];
	char sendto[20];
	char msge[50];
	char member[10][20];
};

void phrases()
{
	printf("****常用语****\n");
	printf("1、你在干嘛呢?\n2、吃饭了么?\n3、再见!\n**************\n");
}

void expression()
{
	printf("1、(^o^)--欢呼  2、{^o~o^}--老人家\n3、^(oo)^--猪头  4、$_$-- 钱钱钱钱\n");
}

void menu()
{
	printf("***********************\n");
	printf("1、私聊\n2、群聊\n");
	printf("3、查看在线人员\n4、查看历史消息\n5、下线\n");
	printf("***********************\n");
}

void login_menu()
{
	printf("1、登录。\n2、注册。\n3、修改密码\n4、忘记密码\n5、退出。\n*********************\n\n\n");
}

void member_on_line(int server_sock)
{
	char send_buff[LEN] = {0};
	struct message send_member;
	int ret = 0;
	
	send_member.flag = 3;
	memcpy(send_buff,&send_member,sizeof(struct message));
	
	ret = send(server_sock,send_buff,LEN,0);
	if(ret < 0)
	{
		perror("member on line error\n");
		sleep(1);
		exit(1);
	}
//	printf("send success\n");
	getchar();
}

int denglu(int sock_fd)
{
	int ret = 0;
	char **result;
	char *errmsg;
	char a = 0;
	char send_buff[1024] = {0};
	char recv_buff[1024] = {0};
	char mibao_daan[20] = {0};
//	char mima[20] = {0};
	char sql[100] = {0};
	struct user user_denglu;
//	recv(sock_fd,zhanghao,1024,0);
//	puts(zhanghao);
	sleep(1);
	while(1)
	{
		system("clear");
		login_menu();
		printf(">");
		scanf("%c",&a);
		getchar();
		//发送操作操作请求
		send(sock_fd,&a,1,0);
		if(ret < 0)
		{
			perror("choose send error\n");
			sleep(1);
			exit(1);
		}

		if(a == '1')
		{
			while(1)
			{
			    system("clear");
				memset(send_buff,0,sizeof(send_buff));
				memset(&user_denglu,0,sizeof(struct user));
			    login_menu();
				printf("*****denglu****\n");
			    printf("zhanghao:");
			    gets(user_denglu.zhanghao);
			    printf("mima:");
			    gets(user_denglu.mima);
				user_denglu.flag = 1;
			    //发送服务器
				
				memcpy(send_buff,&user_denglu,sizeof(struct user));
//				printf("send_buff = %s\n",send_buff);
			    ret = send(sock_fd,send_buff,1024,0);
				if(ret < 0)
				{
					perror("send error\n");
					sleep(1);
					exit(1);
				}
				
				memset(recv_buff,0,sizeof(recv_buff));
				
			    ret = recv(sock_fd,recv_buff,1024,0);
				if(ret < 0)
				{
					perror("recv error\n");
					sleep(1);
					exit(1);
				}
				
				memset(&user_denglu,0,sizeof(struct user));
			    memcpy(&user_denglu,recv_buff,sizeof(recv_buff));
//				printf("flag = %d\n",user_denglu.flag);
				if(user_denglu.flag == 3)
				{
					printf("登录成功!\n");
					strcpy(zhanghao,user_denglu.zhanghao);
					sleep(1);
					return 1;
				}
				else if(user_denglu.flag == 4)
				{
					printf("%s已在线,无法重复登录\n",user_denglu.zhanghao);
					sleep(1);
				}
				else if(user_denglu.flag == 0)
				{
					printf("账号或密码错误\n");
					sleep(1);
				}
			}
		}
		else if(a == '2')
		{
			while(1)
			{	
				system("clear");
				
				memset(send_buff,0,sizeof(send_buff));
				memset(&user_denglu,0,sizeof(struct user));
				login_menu();
				printf("****zhuce****\n");
				printf("账号:");
			    gets(user_denglu.zhanghao);
			    printf("密码:");
			    gets(user_denglu.mima);
				printf("密保:");
				gets(user_denglu.mibao);
				printf("密保答案:");
				gets(user_denglu.mibao_daan);
				user_denglu.flag = 1;
				
				memcpy(send_buff,&user_denglu,sizeof(struct user));
//				printf("send_buff = %s\n",send_buff);
				
//				send(sock_fd,"hello",1024,0);
			    ret = send(sock_fd,send_buff,1024,0);
				if(ret < 0)
				{
					perror("send error\n");
					sleep(1);
					exit(1);
				}
				
				memset(recv_buff,'a',sizeof(recv_buff));
			    ret = recv(sock_fd,recv_buff,1024,0);
				if(ret < 0)
				{
					perror("recv error\n");
					sleep(1);
					exit(1);
				}
				memset(&user_denglu,0,sizeof(struct user));
			    memcpy(&user_denglu,recv_buff,sizeof(recv_buff));
				if(user_denglu.flag == 1)
				{
					printf("注册成功!\n");
					sleep(1);
					break;
				}
				else
				{
					printf("用户已存在,请重新注册!\n");
					sleep(1);
				}
			}
		}
		else if(a == '3')
		{
			system("clear");
			login_menu();
			printf("****change mima****\n");
			printf("账号:");
			gets(user_denglu.zhanghao);
			printf("原密码:");
			gets(user_denglu.mima);
			printf("修改后密码:");
			gets(user_denglu.change_mima);
			memcpy(send_buff,&user_denglu,sizeof(struct user));
			ret = send(sock_fd,send_buff,1024,0);
			if(ret < 0)
			{
				perror("send error\n");
				exit(1);
			}
			
			ret = recv(sock_fd,recv_buff,1024,0);
			if(ret < 0)
			{
				perror("recv error\n");
				exit(1);
			}
			memcpy(&user_denglu,recv_buff,sizeof(recv_buff));
			
			if(user_denglu.flag == 1)
			{
				printf("修改成功!\n");
				sleep(2);
			}
			else if(user_denglu.flag == 0)
			{
				printf("账号或密码不正确\n");
				sleep(1);
			}
		}
		else if(a == '4')
		{
			system("clear");
			login_menu();
			printf("****forget mima****\n");
			printf("账号:");
			gets(user_denglu.zhanghao);
			memcpy(send_buff,&user_denglu,sizeof(struct user));
			ret = send(sock_fd,send_buff,1024,0);
			if(ret < 0)
			{
				perror("send error\n");
				exit(1);
			}
			
			ret = recv(sock_fd,recv_buff,1024,0);
			if(ret < 0)
			{
				perror("recv error\n");
				exit(1);
			}
			memcpy(&user_denglu,recv_buff,sizeof(recv_buff));
			
			
			if(user_denglu.flag == 0)
			{
				printf("账号不存在\n");
				sleep(1);
				continue;
			}
			else if(user_denglu.flag == 1)
			{
				printf("密保:%s\n",user_denglu.mibao);
				printf("输入密保答案:");
				gets(mibao_daan);
				
				if(strcmp(mibao_daan,user_denglu.mibao_daan) == 0)
				{
					printf("账号:%s\n",user_denglu.zhanghao);
					printf("密码:%s\n",user_denglu.mima);
					printf("请牢记!回车键返回");
					getchar();
				}
				else
				{
					printf("密保答案错误\n");
					sleep(1);
				}
			}
		}
		else if(a == '5')
		{
			printf("quit loading...\n");
			sleep(1);
			return 5;
		}
	}	
}

void siliao(int server_sock)
{
	struct message msg_send;
	char send_buff[LEN] = {0};
	int ret = 0;
	char sendto[20] = {0};
	//显示在线人员
	system("clear");
	member_on_line(server_sock);
	printf("\n\n");
	printf("*********siliao********\n");
	printf("****input 'end' quit***\n");
	member_on_line(server_sock);
	memset(&msg_send,0,sizeof(struct message));
	//初始化发送人账号
	strcpy(msg_send.send,zhanghao);
	//初始化功能flag
	msg_send.flag = 1;
	//获取私聊人的账号
	printf("send to>");
	gets(sendto);
	
	while(1)
	{
		strcpy(msg_send.sendto,sendto);
		strcpy(msg_send.send,zhanghao);
		printf(">");
		gets(msg_send.msge);
		if(strcmp(msg_send.msge,"end") == 0)
		{
			printf("loading quiting...\n");
			sleep(2);
			return;
		}
		else
		{
			memset(send_buff,0,LEN);
//			printf("sendto = %s\n",msg_send.sendto);
			memcpy(send_buff,&msg_send,sizeof(struct message));
			ret = send(server_sock,send_buff,LEN,0);
			if(ret < 0)
			{
				perror("siliao send error\n");
				sleep(1);
				exit(1);
			}
		}
	}
}

int ordnary_msg_recv(struct message pmsg)  
{  
    char time_info[25];    
  
    /* handle the msg */  
	if(strlen(pmsg.msge) > 0 && strcmp(pmsg.send,zhanghao) != 0)
	{
		printf("\nMessage:from %s to U:", pmsg.send);  
		puts(pmsg.msge);
		printf(">");
//    	printf("\n\t%s", i_get_time());  
	}
    return 0;  
}

void member_state(struct message pmsg)
{
//	printf("count = %d\n",*(pmsg.member[0]));
	int i = 0;
	printf("****member on line****\n");
	if(pmsg.len > 0)
	{
		for(i = 0;i < pmsg.len;i++)
		{
				puts(pmsg.member[i]);
		}
		printf("*******ENTER*********\n");
	}
	else
	{
		printf("    no boby!    \n");
		printf("**********************\n");
	}
}

void listen_msg(int server_sock)  
{  
    struct message msg_recv; 
	char recv_buff[LEN] = {0};
	int ret = 0;
//    struct sockaddr addr_recv;  
//    int len = ADDR_LEN;  
  
    printf("begin listen...\n");  
  
    for ( ; ; )  
    {
		memset(recv_buff,0,LEN);
		memset(&msg_recv,0,LEN);
		ret = recv(server_sock,recv_buff,LEN,0); 
		if(ret < 0)
		{
			perror("listen_msg error\n");
			return;
		}
		
		memcpy(&msg_recv,recv_buff,LEN);
//		printf("msg_recv.flag = %d\n",msg_recv.flag);
//		saveto_chat(&msg_recv); /* save to history */  
		switch(msg_recv.flag)
		{
			case 1:ordnary_msg_recv(msg_recv);
					break;
			case 4:member_state(msg_recv);
					break;
			default:break;
				
		}
	}  
} 

void quit(int server_sock)
{
	char send_buff[LEN] = {0};
	struct message quit_client;
	int ret = 0;
	quit_client.flag = 5;
	memcpy(send_buff,&quit_client,sizeof(struct message));
	ret = send(server_sock,send_buff,LEN,0);
	if(ret < 0)
	{
		perror("quit error\n");
		sleep(1);
		exit(1);
	}
}

void qunliao(int server_sock)
{
	char send_buff[LEN] = {0};
	struct message msg;
	int ret = 0;
	system("clear");
	printf("*******qunliao********\n");
	printf("****quit input end****\n");
	member_on_line(server_sock);
	while(1)
	{
		msg.flag = 2;
		strcpy(msg.send,zhanghao);
		printf("content>");
		gets(msg.msge);
		if(strcmp(msg.msge,"end") == 0)
		{
			exit(0);
		}
		
		memcpy(send_buff,&msg,sizeof(struct message));
		ret = send(server_sock,send_buff,LEN,0);
		if(ret < 0)
		{
			perror("send error\n");
			exit(1);
		}
	}
}

int main(int argc, const char *argv[])
{
	int sock_fd,listen_fd;
	int ret;
	pid_t fd;
	int num,num1,num2;	
	struct sockaddr_in serveraddr;
	struct sockaddr_in clientaddr;
	int sin_size;
	char buf[2048] = {0};
	char *user_name;
	char name[20] = {0};
	int fun = 0;
//	char receive_words[100] = {0};
//	char receive_name[100] = {0};
//	char receive_flag[100] = {0};
	
//	denglu(user_name);
	sock_fd = socket(AF_INET,SOCK_STREAM,0);
	if(sock_fd == -1)
	{
		printf("socket error:%s\n",strerror(errno));
		exit(ERROR);
	}
	else 
	{
		printf("socket success\n");
	}
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(portnumber);
	serveraddr.sin_addr.s_addr = inet_addr(argv[1]);

	
	ret = connect(sock_fd, (struct sockaddr *)&serveraddr,sizeof(struct sockaddr));
	if(ret < 0)
	{
		printf("connect error\n");	
		exit(1);
	}
	else if(ret == 0)
	{
		printf("connect success\n");
	}
	//登录注册界面
	ret = denglu(sock_fd);
	//此为登录界面就退出
	if(ret == 5)
	{
		return 0;
	}
	
	fd = fork();

	if(fd == 0)
	{
		listen_msg(sock_fd);
	}
	else if(fd > 0)
	{
		while(1)
		{
			sleep(1);
			system("clear");
			menu();
	
			printf(">");
			scanf("%d",&fun);
			getchar();
//			printf("11111\n");
			switch(fun)
			{
				case 1: siliao(sock_fd);
						break;
				case 2: qunliao(sock_fd);
						break;
				case 3:member_on_line(sock_fd);
					    break;
//				case 4: break;
				case 5:quit(sock_fd);
						break;
				default:break;
			}
			if(fun == 5)
			{
				printf("quit client loading...");
				sleep(1);
				break;
			}
		}
	}
	else
	{
		perror("fork error\n");
	}
	
	close(sock_fd);
	return 0;
}
server.c
/*************************************************************************
	> File Name: server.c
	> Author: caojian
	> Mail: [email protected] 
	> Created Time: 2018年02月08日 星期四 12时49分14秒
 ************************************************************************/

 /*数据库data,表data
	zhanghao,mima,socket,state,mibao,mibao_daan
*/

#include <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sqlite3.h>
#include <math.h>

#define LEN sizeof(struct message)
#define PORT 1234
#define FILE_MAX_LEN 64
#define DATA "/home/wechat/server/data.db"

char filename[FILE_MAX_LEN + 1];
static char *errmsg = NULL;

struct user
{
	char zhanghao[20];
	char mima[20];
	char change_mima[20];
	char mibao[20];
	char mibao_daan[20];
	int flag;    //0、error.1、success
};

struct message
{
	int flag;
	int len;
	char send[20];
	char sendto[20];
	char msge[50];
	char member[10][20];
};

char *i_get_time()  
{  
    time_t time_now;  
    time(&time_now);  
  
    return(ctime(&time_now));  
} 

void data_init()
{
	char sql[1024] = {0};
	sqlite3 *db;
	int ret = 0;
	sqlite3_open(DATA,&db);
	
	ret = sqlite3_exec(db,"update data set state = '0'",0,0,&errmsg);
	if(ret < 0)
	{
		perror("update error\n");
		sqlite3_close(db);
		exit(1);
	}
	else
	{
		printf("update success\n");
		sqlite3_close(db);
	}
}

void member_on_line(int client_sock)
{
	struct message mem_on_line;
	char **result;
	char send_buff[LEN] = {0};
	int nrow = 0;
	int ncolumn = 0;
	int i = 0;
	int ret = 0;
	char count = 0;
	sqlite3 *db;
	
	sqlite3_open(DATA,&db);
	
	sqlite3_get_table(db,"select zhanghao from data where state = '1'",&result,&nrow,&ncolumn,&errmsg);
//	printf("nrow = %d\n",nrow);
	mem_on_line.flag = 4;
	mem_on_line.len = nrow;
	
	if(nrow > 0)
	{
		for(i = 0;i < nrow;i++)
		{
			strcpy(mem_on_line.member[i],result[i+1]);
		}
	}
	memcpy(send_buff,&mem_on_line,sizeof(struct message));
	
	ret  = send(client_sock,send_buff,LEN,0);
	if(ret < 0)
	{
		perror("error\n");
		sqlite3_close(db);
		exit(1);
	}
	else
	{
		printf("send success\n");
	}
	
	sqlite3_close(db);
	
}

int denglu(int user_sock)
{
//	char zhanghao[20] = {0};
//	char mima[20] = {0};
	char recv_buff[1024] = {0};
	char send_buff[1024] = {0};
	char choose = 0;
	sqlite3 *db;
	int nrow = 0;
	int ncolumn = 0;
	int ret = 0;
	char sql[1024] = {0};
	char **result;
	struct user user_denglu;
	//打开数据库
	ret = sqlite3_open(DATA,&db);
	if(ret < 0)
	{
		perror("open error\n");
		exit(1);
	}
	else
	{
		printf("open success\n");
	}
	
//	send(user_sock,"denglu kaishi",1024,0);
	while(1)
	{
		recv(user_sock,&choose,1,0);
		
		//登录
		if(choose == '1')
		{
			while(1)
			{
				printf("a login request come!\n");
//				memset(zhanghao,0,sizeof(zhanghao));
//				memset(mima,0,sizeof(mima));
				memset(recv_buff,'a',1024);					//清空接收
				memset(&user_denglu,0,sizeof(struct user));//清空结构体
				ret = recv(user_sock,recv_buff,1024,0);
				if(ret < 0)
				{
					perror("error\n");
					sqlite3_close(db);
					exit(1);
				}else if(ret == 0)
				{
					sqlite3_close(db);
					return 3;
				}
					
				memcpy(&user_denglu,recv_buff,sizeof(struct user));
//				printf("zhanghao = %s\n",user_denglu.zhanghao);
//				printf("mima = %s\n",user_denglu.mima);
				sprintf(sql,"select mima from data where zhanghao = '%s'",user_denglu.zhanghao);
			    sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
			    printf("nrow = %d,ncolumn = %d\n",nrow,ncolumn);
//				printf("mima = %s\n",result[1]);
				//用户或密码错误
				if(nrow == 0)
				{
					printf("wu yong hu \n");
					user_denglu.flag = 0;
					memset(send_buff,0,1024);//清空发送
					memcpy(send_buff,&user_denglu,sizeof(user_denglu));
					ret = send(user_sock,send_buff,sizeof(send_buff),0);
					if(ret < 0)
					{
						perror("send error\n");
						sleep(1);
						return 5;
					}	
				}
				else if(strcmp(result[1],user_denglu.mima) == 0) 
				{
					sprintf(sql,"select state from data where zhanghao = '%s'",user_denglu.zhanghao);
					sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
					if(strcmp(result[1],"1") == 0)
					{
						user_denglu.flag = 4;
						memset(send_buff,0,1024);//清空发送
						memcpy(send_buff,&user_denglu,sizeof(user_denglu));
						ret = send(user_sock,send_buff,sizeof(send_buff),0);
//						sleep(1);
						if(ret < 0)
						{
							perror("send error\n");
							sleep(1);
							return 5;
						}
						
						continue;
					}
					sprintf(sql,"update data set socket = %d where zhanghao = '%s'",user_sock,user_denglu.zhanghao);
					sqlite3_exec(db,sql,0,0,&errmsg);
					sprintf(sql,"update data set state = '1' where zhanghao = '%s'",user_denglu.zhanghao);
					sqlite3_exec(db,sql,0,0,&errmsg);
					printf("updata success\n");
					sqlite3_close(db);
					user_denglu.flag = 3;
					memset(send_buff,0,1024);//清空发送
					memcpy(send_buff,&user_denglu,sizeof(user_denglu));
					ret = send(user_sock,send_buff,sizeof(send_buff),0);
//					sleep(1);
					if(ret < 0)
					{
						perror("send error\n");
						sleep(1);
						exit(1);
					}	
					return 1;
				}
				else
				{
					printf("mima error\n");
					user_denglu.flag = 0;
					memset(send_buff,'a',1024);//清空发送
					memcpy(send_buff,&user_denglu,sizeof(user_denglu));
					ret = send(user_sock,send_buff,sizeof(send_buff),0);
					if(ret < 0)
					{
						perror("send error\n");
						sleep(1);
						exit(1);
					}	
				}
			}
		}//注册
		else if(choose == '2')
		{
			printf("a regit requet come:\n");
			while(1)
			{
//				recv(user_sock,sql,1024,0);
//				puts(sql);
			    memset(recv_buff,0,1024);					//清空接收
				memset(&user_denglu,0,sizeof(struct user));//清空结构体
				printf("user_sock = %d\n",user_sock);
				ret = recv(user_sock,recv_buff,1024,0);
				if(ret < 0)
				{
					perror("recv error\n");
					sqlite3_close(db);
					sleep(1);
					return 5;
				}
				
				memcpy(&user_denglu,recv_buff,sizeof(recv_buff));
				printf("zhanghao = %s\n",user_denglu.zhanghao);
				printf("mima = %s\n",user_denglu.mima);
				
//				sqlite3_get_table(db,"select zhanghao from data where zhanghao = 'caojian'",&result,&nrow,&ncolumn,&errmsg);
//				printf("zhanghao = %s\n",result[1]);
//				getchar();
				
			    sprintf(sql,"select zhanghao from data where zhanghao = '%s'",user_denglu.zhanghao);
//				puts(sql);
			    sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
//				printf("22222222222\n");
				printf("nrow = %d\n",nrow);
			    if(nrow == 0)//数据库中无此用户
			    {
			    	sprintf(sql,"insert into data values('%s','%s',%d,'0','%s','%s')",user_denglu.zhanghao,user_denglu.mima,user_sock,user_denglu.mibao,user_denglu.mibao_daan);
			    	sqlite3_exec(db,sql,0,0,&errmsg);
			    	printf("注册成功\n");
			    	user_denglu.flag = 1;
					memset(send_buff,0,1024);//清空发送
					memcpy(send_buff,&user_denglu,sizeof(user_denglu));
					ret = send(user_sock,send_buff,sizeof(send_buff),0);
					if(ret < 0)
					{
						perror("send error\n");
						sleep(1);
						return 5;
					}
					else
					{
						printf("zhuce success\n");
						sleep(1);
					}
			    	break;
			    }
			    else
			    {
			    	user_denglu.flag = 0;
					memset(send_buff,0,1024);//清空发送
					memcpy(send_buff,&user_denglu,sizeof(user_denglu));
					ret = send(user_sock,send_buff,sizeof(send_buff),0);
					if(ret < 0)
					{
						perror("send error\n");
						sqlite3_close(db);
						sleep(1);
						return 5;
					}
					
			    }
			}
		}
		else if(choose == '3')
		{
			printf("user_sock = %d,change mima\n",user_sock);
			ret = recv(user_sock,recv_buff,1024,0);
			if(ret < 0)
			{
				perror("recv error\n");
				sqlite3_close(db);
				return 5;
			}
			
			memcpy(&user_denglu,recv_buff,1024);
			sprintf(sql,"select mima from data where zhanghao = '%s'",user_denglu.zhanghao);
			sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
			printf("nrow = %d,ncolumn = %d\n",nrow,ncolumn);
			//用户或密码错误
			if(nrow == 0)
			{
				printf("wu yong hu \n");
				user_denglu.flag = 0;
				memset(send_buff,0,1024);//清空发送
				memcpy(send_buff,&user_denglu,sizeof(user_denglu));
				ret = send(user_sock,send_buff,sizeof(send_buff),0);
				if(ret < 0)
				{
					perror("send error\n");
					sqlite3_close(db);
					return 5;
				}	
			}
			else if(strcmp(result[1],user_denglu.mima) == 0) 
			{
				sprintf(sql,"update data set mima = %s where zhanghao = '%s'",user_denglu.change_mima,user_denglu.zhanghao);
				sqlite3_exec(db,sql,0,0,&errmsg);
				user_denglu.flag = 1;
				memset(send_buff,0,1024);//清空发送
				memcpy(send_buff,&user_denglu,sizeof(user_denglu));
				ret = send(user_sock,send_buff,sizeof(send_buff),0);
//				sleep(1);
				if(ret < 0)
				{
					perror("send error\n");
					sqlite3_close(db);
					return 5;
				}	
			}
			else
			{
				printf("mima error\n");
				user_denglu.flag = 0;
				memset(send_buff,'a',1024);//清空发送
				memcpy(send_buff,&user_denglu,sizeof(user_denglu));
				ret = send(user_sock,send_buff,sizeof(send_buff),0);
				if(ret < 0)
				{
					perror("send error\n");
					sqlite3_close(db);
					return 5;
				}	
			}
		}
		else if(choose == '4')
		{
			printf("user_sock = %d,forget mima\n",user_sock);
			ret = recv(user_sock,recv_buff,1024,0);
			if(ret < 0)
			{
				perror("recv error\n");
				sqlite3_close(db);
				return 5;
			}
			
			memcpy(&user_denglu,recv_buff,1024);
			sprintf(sql,"select zhanghao from data where zhanghao = '%s'",user_denglu.zhanghao);
			sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
			printf("nrow = %d,ncolumn = %d\n",nrow,ncolumn);
			//用户或密码错误
			if(nrow == 0)
			{
				printf("wu yong hu \n");
				user_denglu.flag = 0;
				memset(send_buff,0,1024);//清空发送
				memcpy(send_buff,&user_denglu,sizeof(user_denglu));
				ret = send(user_sock,send_buff,1024,0);
				if(ret < 0)
				{
					perror("send error\n");
					sqlite3_close(db);
					return 5;
				}	
			}
			else
			{
				//三次查询可改进
				sprintf(sql,"select mima from data where zhanghao = '%s'",user_denglu.zhanghao);
				sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
//				printf("nrow = %d,ncolumn = %d\n",nrow,ncolumn);
				strcpy(user_denglu.mima,result[1]);//密码
//				printf("3333\n");
				sprintf(sql,"select mibao from data where zhanghao = '%s'",user_denglu.zhanghao);
				sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
				strcpy(user_denglu.mibao,result[1]);//密保
				
				sprintf(sql,"select mibao_daan from data where zhanghao = '%s'",user_denglu.zhanghao);
				sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
				strcpy(user_denglu.mibao_daan,result[1]);//密保答案
				
				user_denglu.flag = 1;
//				printf("111\n");
//				memset(send_buff,0,1024);//清空发送
				memcpy(send_buff,&user_denglu,sizeof(user_denglu));
				ret = send(user_sock,send_buff,1024,0);
//				sleep(1);
				if(ret < 0)
				{
					perror("send error\n");
					sqlite3_close(db);
					return 5;
				}
//				printf("2222\n");
			}
		}
		else if(choose == '5')
		{
			sqlite3_close(db);
			return 5;
		}	
	}
}

void si_message(struct message send_msg)
{
	char recv_buff[LEN] = {0};
	char send_buff[LEN] = {0};
	char sql[1024] = {0};
	int ret = 0;
	int nrow = 0;
	int ncolumn = 0;
	char **result;
	int send_to_sock;
	sqlite3 *db;
	sqlite3_open(DATA,&db);
	
	printf("sendto = %s\n",send_msg.sendto);
	sprintf(sql,"select socket from data where zhanghao = '%s'",send_msg.sendto);
	sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);
	if(nrow == 0)
	{
		printf("send error\n");
		sleep(1);
		return;
	}
	send_to_sock = atoi(result[1]);
//	printf("send_to_sock = %d\n",send_to_sock);
	memset(send_buff,0,LEN);
	memcpy(send_buff,&send_msg,sizeof(struct message));
	ret = send(send_to_sock,send_buff,LEN,0);
	if(ret < 0)
	{
		perror("send error\n");
		sleep(1);
		return;
	}
	else
	{
		printf("send success\n");
	}
}

void quit(sock_client)
{
	sqlite3 *db;
	int ret = 0;
	char sql[1024] = {0};
	
	sqlite3_open(DATA,&db);
	sprintf(sql,"update data set state = '0' where socket = %d",sock_client);
	ret = sqlite3_exec(db,sql,0,0,&errmsg);
	if(ret < 0)
	{
		perror("update error\n");
		sqlite3_close(db);
		return;
	}
	
	sqlite3_close(db);
}

void qun_message(struct message pmsg)
{
	char sql[2048] = {0};
	char send_buff[LEN] = {0};
	int ret = 0;
	char **result;
	int nrow;
	int ncolumn;
	sqlite3 *db;
	int i = 1;
	int sock = 0;
	memset(send_buff,0,LEN);
	pmsg.flag = 1;
	memcpy(send_buff,&pmsg,sizeof(struct message));
	
	sqlite3_open(DATA,&db);
	sqlite3_get_table(db,"select socket from data where state = '1'",&result,&nrow,&ncolumn,&errmsg);
	
	for(i = 1;i <= nrow;i++)
	{
		sock = atoi(result[i]);
		ret = send(sock,send_buff,LEN,0);
		if(ret < 0)
		{
			perror("send error\n");
			return;
		}
	}
}

//处理客户端函数
static void *handle_client(void *arg)
{
	sqlite3 *db;
	int sock_client = (int)arg;
	int ret = 0;
	char recv_buff[LEN] = {0};
	char send_buff[LEN] = {0};
	char sql[100] = {0};
	char fun = 0;
	int send_sock = 0;
	char **result;
	int nrow;
	int ncolumn;
	struct message msg;
	printf("uesr_sock = %d\n",sock_client);
	
	ret = denglu(sock_client);
	//如果用户在登录界面就退出,那么就结束线程
	if(ret == 5)
	{
		return;
	}
	
	for(;;)
	{
		memset(&msg,0,LEN);
		memset(recv_buff,0,LEN);
//		printf("111111\n");
		ret = recv(sock_client,recv_buff,LEN,0);
		if(ret <= 0)
		{
			perror("recv error\n");
			return;
		}
		
		memcpy(&msg,recv_buff,LEN);
//		printf("22222\n");
//		printf("sendto = %s\n",msg.sendto);
//		printf("msg.flag = %d\n",msg.flag);
		
		switch(msg.flag)
		{
			case 1:si_message(msg);
					break;
			case 2:qun_message(msg);
					break;
			case 3:member_on_line(sock_client);
					break;
			case 5:quit(sock_client);
			default:break;
		}
	}

}

int main(int argc,char *argv[])
{
	int sockfd;
	int new_fd;
	int ret = 0;
	struct sockaddr_in my_addr;
	struct sockaddr_in client_addr;
	int sin_size;
	int numbytes;
	pthread_t cli_thread;

	//创建TCP套接字
	sockfd = socket(AF_INET,SOCK_STREAM,0);

	if(sockfd < 0 )
	{
		perror("socket error!\n");
		exit(1);
	}
	else
	{
		perror("socket success...\n");
		sleep(1);
	}

	//初始化端口信息
	memset(&my_addr,0,sizeof(struct sockaddr));
	my_addr.sin_family = AF_INET;    //IPV4
	my_addr.sin_port = htons(PORT);
	my_addr.sin_addr.s_addr = inet_addr(argv[1]);

	//绑定
	ret = bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr));
	if(ret < 0)
	{
		perror("bind error!\n");
		exit(1);
	}
	else
	{
		perror("bind success...\n");
		sleep(1);
	}

	//侦听
	ret = listen(sockfd,10);
	if(ret < 0)
	{
		perror("listen error!\n");
		exit(1);
	}
	else
	{		
		perror("listen success...\n");
		sleep(1);
	}

	printf("server loading...\n");
	sleep(1);
	data_init();
	
	while(1)
	{
		sin_size = sizeof(struct sockaddr_in);
		new_fd = accept(sockfd,(struct sockaddr *)&client_addr,&sin_size);
		if(new_fd < 0)
		{

			continue;
		}
		printf("---client (ip=%s:port=%d) requst---  \n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
		
		pthread_create(&cli_thread,NULL,(void *)handle_client,(void *)new_fd);
		
	}
	

	close(sockfd);
    return 0;
}

 

猜你喜欢

转载自blog.csdn.net/cxycj123/article/details/79472747