项目要求:
1. 登录注册功能,不能重复登录,重复注册
2. 单词查询功能
3. 历史记录功能,存储单词,意思,以及查询时间
4. 基于TCP,支持多客户端连接
5. 采用数据库保存用户信息与历史记录
6. 将dict.txt的数据导入到数据库中保存。
7. 按下ctrl+c退出客户端后,注销该客户端的登录信息
格式要求:
1. main函数只跑逻辑,不允许跑功能代码
2. 功能代码封装成函数
服务器
ser.c定义文件
#include<stdio.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<time.h>
#include<sqlite3.h>
#include"ser.h"
void handler(int sig)
{
while(waitpid(-1,NULL,WNOHANG)>0);
}
int do_insert(sqlite3* ser,char word[],char meaning[])
{
char buf[256] = "";
bzero(buf,sizeof(buf));
sprintf(buf,"insert into serdic (word,meaning) values (\"%s\",\"%s\");",word,meaning);
char* errmsg = NULL;
if(sqlite3_exec(ser,buf, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
return 0;
}
int dict_input(sqlite3* ser)
{
FILE * fp = fopen("dict.txt","r");
if(fp == NULL)
{
MSG_ERR("fopen");
}
char word[128] = "";
char meaning[128] = "";
char buf[256] = "";
int flag = 0;
int sum = 0;
while(1)
{
bzero(word,sizeof(word));
bzero(meaning,sizeof(meaning));
bzero(buf,sizeof(buf));
if(fgets(buf,sizeof(buf),fp) == NULL)
{
break;
}
int num = 0;
int m = 0;
int n = 0;
while(buf[num] != '\n')
{
if(buf[num] == ' ' && buf[num+1] == ' ')
{
flag++;
}
if(flag < 1)
{
word[m] = buf[num];
m++;
}
else
{
meaning[n] = buf[num];
n++;
}
num++;
}
flag = 0;
do_insert(ser,word,meaning);
}
return 0;
}
sqlite3* create_sq()
{
sqlite3* ser = NULL;
if(sqlite3_open("./ser.db",&ser) != SQLITE_OK)
{
printf("err_code:%d\n", sqlite3_errcode(ser));
printf("errmsg:%s\n", sqlite3_errmsg(ser));
fprintf(stderr, "__%d__ sqlite3_open failed\n", __LINE__);
return NULL;
}
printf("------sqlite3_open-success-------\n");
char* sq1 = "create table if not exists serdic\
(word char,meaning char);";
char* errmsg1 = NULL;
if(sqlite3_exec(ser, sq1, NULL, NULL, &errmsg1) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg1);
return NULL;
}
printf("------create-serdic-success------\n");
char* sq2 = "create table if not exists usrinf\
(name char,password char,status char);";
char* errmsg2 = NULL;
if(sqlite3_exec(ser, sq2, NULL, NULL, &errmsg2) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg2);
return NULL;
}
printf("------create-usrinf-success------\n");
char* sq3 = "create table if not exists usrrec\
(name char,word char,time char);";
char* errmsg3 = NULL;
if(sqlite3_exec(ser, sq3, NULL, NULL, &errmsg3) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg3);
return NULL;
}
printf("------create-usrrec-success------\n");
dict_input(ser);
return ser;
}
int his_insert(sqlite3 *ser,char word[],char head[])
{
time_t t=0;
struct tm* info=NULL;
char str[64]="";
char buf[128]="";
bzero(str,sizeof(str));
bzero(buf,sizeof(buf));
time(&t);
info=localtime(&t);
sprintf(str,"%4d-%02d-%02d %02d:%02d:%02d\n",info->tm_year+1900,\
info->tm_mon+1,info->tm_mday,info->tm_hour,info->tm_min,\
info->tm_sec);
sprintf(buf,"insert into usrrec (name,word,time) values (\'%s\',\'%s\',\'%s\');",head,word,str);
char* errmsg1 = NULL;
if(sqlite3_exec(ser,buf, NULL, NULL, &errmsg1) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg1);
return -1;
}
return 0;
}
int ser_net()
{
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
MSG_ERR("socket");
}
printf("/-----create socket success-----/\n");
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
MSG_ERR("setsockopt");
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
MSG_ERR("bind");
}
printf("/----------bind success---------/\n");
if(listen(sfd,10)<0)
{
MSG_ERR("lisetn");
}
printf("/---------listen success--------/\n");
return sfd;
}
int inf_search(sqlite3* ser,char head[])
{
char buf[128]="";
bzero(buf,sizeof(buf));
sprintf(buf,"select * from usrinf where name like \'%s\';",head);
char* errmsg1 = NULL;
char **dbresult;
int nrow,ncolumn;
if(sqlite3_get_table(ser,buf, &dbresult, &nrow, &ncolumn, &errmsg1) == SQLITE_OK)
{
if(nrow != 0)
{
return 1;
}
}
return 0;
}
int sta_search(sqlite3* ser,char head[],char tail[])
{
char buf[128]="";
bzero(buf,sizeof(buf));
sprintf(buf,"select * from usrinf where name like \'%s\' and password like \'%s\' and status like \'%s\';",head,tail,"online");
char* errmsg1=NULL;
char **dbresult;
int nrow,ncolumn;
if(sqlite3_get_table(ser,buf, &dbresult, &nrow, &ncolumn, &errmsg1) == SQLITE_OK)
{
if(nrow != 0)
{
return 1;
}
}
return 0;
}
int jug_pwd(sqlite3* ser,char head[],char tail[])
{
char buf[128]="";
bzero(buf,sizeof(buf));
sprintf(buf,"select * from usrinf where name like \'%s\' and password like \'%s\';",head,tail);
char* errmsg1=NULL;
char **dbresult;
int nrow,ncolumn;
if(sqlite3_get_table(ser,buf, &dbresult, &nrow, &ncolumn, &errmsg1) == SQLITE_OK)
{
if(nrow != 0)
{
return 1;
}
}
return 0;
}
int sta_change(sqlite3* ser,char head[],int newfd)
{
char buf[128]="";
bzero(buf,sizeof(buf));
sprintf(buf,"update usrinf set status=\'%s\' where name=\'%s\';","offline",head);
char* errmsg1=NULL;
if(sqlite3_exec(ser,buf, NULL, NULL, &errmsg1) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg1);
return -1;
}
char mes[32]="";
strcpy(mes,"you have offline");
if(send(newfd,mes,sizeof(mes),0)<0)
{
MSG_ERR("send");
}
return 0;
}
int inf_insert(sqlite3* ser,char head[],char tail[])
{
char buf[128] = "";
bzero(buf,sizeof(buf));
sprintf(buf,"insert into usrinf (name,password,status) values (\'%s\',\'%s\',\'%s\');",head,tail,"online");
char* errmsg1 = NULL;
if(sqlite3_exec(ser,buf, NULL, NULL, &errmsg1) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg1);
return -1;
}
return 0;
}
int meaning_search(sqlite3* ser,int newfd,char word[])
{
char buf[128]="";
char meaning[64]="";
bzero(buf,sizeof(buf));
bzero(meaning,sizeof(meaning));
sprintf(buf,"select * from serdic where word like \'%s\';",word);
char* errmsg1=NULL;
char **dbresult;
int nrow,ncolumn;
if(sqlite3_get_table(ser,buf, &dbresult, &nrow, &ncolumn, &errmsg1) != SQLITE_OK)
{
fprintf(stderr,"_%d_sqlite_get_table:%s\n",__LINE__,errmsg1);
return -1;
}
if(nrow != 0)
{
strcat(meaning,dbresult[3]);
if(send(newfd,meaning,sizeof(meaning),0)<0)
{
MSG_ERR("send");
}
return 1;
}
else
{
strcat(meaning,"The word was not queried");
if(send(newfd,meaning,sizeof(meaning),0)<0)
{
MSG_ERR("send");
}
}
return 0;
}
int record_search(sqlite3 *ser,int newfd,char head[])
{
char buf[512]="";
bzero(buf,sizeof(buf));
sprintf(buf,"select * from usrrec where name like \'%s\';",head);
char* errmsg1=NULL;
char **dbresult;
int nrow,ncolumn;
if(sqlite3_get_table(ser,buf, &dbresult, &nrow, &ncolumn, &errmsg1) != SQLITE_OK)
{
fprintf(stderr,"_%d_sqlite_get_table:%s\n",__LINE__,errmsg1);
return -1;
}
int flag=0;
int i=0;
int j=0;
bzero(buf,sizeof(buf));
for(i=3;i<(nrow+1)*ncolumn;i++)
{
strcat(buf,dbresult[i]);
j++;
if(j==3)
{
continue;
j=0;
}
strcat(buf," ");
}
if(send(newfd,buf,sizeof(buf),0)<0)
{
MSG_ERR("send");
}
return 0;
}
int rcv_cli_msg(sqlite3* ser,int newfd,struct sockaddr_in cin)
{
char buf[128]="";
char str[128]="";
char head[64]="";
char tail[64]="";
ssize_t res=0;
while(1)
{
bzero(buf,sizeof(buf));
res=recv(newfd,buf,sizeof(buf),0);
if(res<0)
{
MSG_ERR("recv");
}
else if(0==res)
{
printf("[%s : %d] newfd = %d client off-line\n",\
inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),newfd);
return -1;
}
if(buf[0]=='@' || buf[0]=='#')
{
int flag = 0;
int i=1;
int j=0;
while(buf[i] != 0)
{
if(buf[i] == '/')
{
flag=1;
}
if(flag == 0)
{
head[i-1]=buf[i];
}
else
{
tail[j]=buf[i+1];
j++;
}
i++;
}
if(inf_search(ser,head) == 1)
{
bzero(str,sizeof(str));
if(buf[0]=='@')
{
strcpy(str,"@This account is registered");
}
else if(buf[0]=='#')
{
if(sta_search(ser,head,tail)==1)
{
strcpy(str,"#This account is logged in");
}
else
{
if(jug_pwd(ser,head,tail)==1)
{
strcpy(str,"!Logged in success");
}
else
{
strcpy(str,"#Password is wrong");
}
}
}
if(send(newfd,str,sizeof(str),0) < 0)
{
MSG_ERR("send");
}
}
else
{
bzero(str,sizeof(str));
if(buf[0]=='@')
{
inf_insert(ser,head,tail);
strcpy(str,"!Registered success");
}
else if(buf[0]=='#')
{
strcpy(str,"#The account does not exist");
}
if(send(newfd,str,sizeof(str),0) < 0)
{
MSG_ERR("send");
}
}
}
else
{
if(buf[0]=='(')
{
char word[128]="";
strcpy(word,buf+1);
if(meaning_search(ser,newfd,word)==1)
{
his_insert(ser,word,head);
}
}
else if(buf[0]==')')
{
char head[128]="";
strcpy(head,buf+1);
record_search(ser,newfd,head);
}
else
{
sta_change(ser,head,newfd);
}
}
}
}
ser.h声明文件
#ifndef __server_h__
#define __server_h__
#define MSG_ERR(msg) do{fprintf(stderr,"_%d_",__LINE__);perror(msg);return -1;}while(0)
#define PORT 8888
#define IP "192.168.31.240"
typedef void(*sighandler_t)(int);
void handler(int sig);
int do_insert(sqlite3* ser,char word[],char meaning[]);
int dict_input(sqlite3* ser);
sqlite3* create_sq();
int his_insert(sqlite3 *ser,char word[],char head[]);
int ser_net();
int inf_search(sqlite3* ser,char head[]);
int sta_search(sqlite3* ser,char head[],char tail[]);
int jug_pwd(sqlite3* ser,char head[],char tail[]);
int sta_change(sqlite3* ser,char head[],int newfd);
int inf_insert(sqlite3* ser,char head[],char tail[]);
int meaning_search(sqlite3* ser,int newfd,char word[]);
int record_search(sqlite3 *ser,int newfd,char head[]);
int rcv_cli_msg(sqlite3* ser,int newfd,struct sockaddr_in cin);
#endif
sermain.c主函数
#include<stdio.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<time.h>
#include<sqlite3.h>
#include"ser.h"
int main()
{
sighandler_t s=signal(17,handler);
if(SIG_ERR==s)
{
MSG_ERR("signal");
}
sqlite3* ser=create_sq();
int sfd=ser_net();
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
int newfd=0;
pid_t pid=0;
while(1)
{
newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
printf("[%s : %d] newfd = %d client on-line\n",\
inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),newfd);
if(newfd<0)
{
MSG_ERR("accept");
}
pid=fork();
if(pid>0)
{
close(newfd);
}
else if(0==pid)
{
close(sfd);
rcv_cli_msg(ser,newfd,cin);
close(newfd);
exit(0);
}
else
{
MSG_ERR("fork");
}
}
close(sfd);
return 0;
}
客户端
cli.c定义文件
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<signal.h>
#include"cli.h"
void handler(int sig)
{
char mes[32]="";
strcpy(mes,"quit");
if(send(sfd,mes,sizeof(mes),0)<0)
{
perror("send");
return;
}
bzero(mes,sizeof(mes));
if(recv(sfd,mes,sizeof(mes),0)<0)
{
perror("recv");
return;
}
printf("\n%s\n",mes);
exit(0);
}
int cli_net()
{
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd < 0)
{
MSG_ERR("socket");
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
if(connect(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
MSG_ERR("connect");
}
return sfd;
}
int usr_inf(int sfd)
{
printf("/------1.Enroll------/\n");
printf("/------2.Login-------/\n\n");
int choice;
char buf[128]="";
char ID[63]="";
char password[63]="";
printf("Enter your choice >>> ");
scanf("%d",&choice);
while(getchar() != '\n');
bzero(buf,sizeof(buf));
bzero(ID,sizeof(ID));
bzero(password,sizeof(password));
printf("Enter your ID >>> ");
fgets(ID,sizeof(ID),stdin);
ID[strlen(ID)-1] = 0;
printf("Enter your password >>> ");
fgets(password,sizeof(password),stdin);
password[strlen(password)-1] = 0;
if(choice==1)
{
sprintf(buf,"%c%s%c%s",'@',ID,'/',password);
}
else
{
sprintf(buf,"%c%s%c%s",'#',ID,'/',password);
}
if(send(sfd,buf,sizeof(buf),0) < 0)
{
MSG_ERR("send");
}
bzero(buf,sizeof(buf));
if(recv(sfd,buf,sizeof(buf),0)<0)
{
MSG_ERR("recv");
}
printf("\nPrompt>>>");
if(buf[0]=='@')
{
printf("%s\n\n",buf+1);
return -1;
}
else if(buf[0]=='#')
{
printf("%s\n\n",buf+1);
return -1;
}
else if(buf[0]=='!')
{
printf("%s\n\n",buf+1);
return 0;
}
}
int word_inquire(int sfd)
{
char word[63]="";
char meaning[64]="";
char str[128]="";
printf("Enter the word>>>");
bzero(word,sizeof(word));
fgets(word,sizeof(word),stdin);
word[strlen(word)-1]=0;
sprintf(str,"%c%s",'(',word);
if(send(sfd,str,sizeof(str),0)<0)
{
MSG_ERR("send");
}
bzero(meaning,sizeof(meaning));
if(recv(sfd,meaning,sizeof(meaning),0)<0)
{
MSG_ERR("recv");
}
printf("meaning:%s\n",meaning);
return 0;
}
int record_inquire(int sfd)
{
char buf[512]="";
char str[128]="";
char ID[31]="";
printf("\nEnter the ID>>>");
fgets(ID,sizeof(ID),stdin);
ID[strlen(ID)-1]=0;
sprintf(str,"%c%s",')',ID);
if(send(sfd,str,sizeof(str),0)<0)
{
MSG_ERR("send");
}
bzero(buf,sizeof(buf));
if(recv(sfd,buf,sizeof(buf),0)<0)
{
MSG_ERR("recv");
}
printf("\nUser Record>>>\n");
printf("%s\n",buf);
return 0;
}
int usr_quit(int sfd)
{
char mes[32]="";
strcpy(mes,"quit");
printf("%s\n",mes);
if(send(sfd,mes,sizeof(mes),0)<0)
{
MSG_ERR("send");
}
bzero(mes,sizeof(mes));
if(recv(sfd,mes,sizeof(mes),0)<0)
{
MSG_ERR("recv");
}
printf("%s\n",mes);
}
cli.h声明文件
#ifndef __client_h__
#define __client_h__
#define MSG_ERR(msg) do{fprintf(stderr,"_%d_",__LINE__);perror(msg);return -1;}while(0)
#define PORT 8888
#define IP "192.168.31.240"
typedef void(*sighandler_t)(int);
int sfd;
void handler(int sig);
int cli_net();
int usr_inf(int sfd);
int word_inquire(int sfd);
int record_inquire(int sfd);
int usr_quit(int sfd);
#endif
~
climain.c主函数
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<signal.h>
#include"cli.h"
int main()
{
sighandler_t s=signal(2,handler);
if(SIG_ERR==s)
{
MSG_ERR("signal");
}
sfd=cli_net();
char buf[128]="";
while(usr_inf(sfd)!=0);
ssize_t res=0;
int cho;
while(1)
{
printf("/----1.Query word------/\n");
printf("/----2.Query record----/\n");
printf("/----3.Quit systeam----/\n");
printf("\nselect>>>");
scanf("%d",&cho);
while(getchar()!='\n');
if(cho==1)
{
word_inquire(sfd);
}
else if(cho==2)
{
record_inquire(sfd);
}
else
{
usr_quit(sfd);
exit(0);
}
printf("\n");
}
close(sfd);
return 0;
}
运行结果图
用户数据 数据库
名字,密码,状态,在线是online,退出是offline
用户记录 数据库
?名字,单词,时间
(同一用户查询多次)
?
|