总结遇到的问题:
在一开始构思架构的时候,肯定是采用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: 13260888275@163.com
> 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;
}