//服务器
#include <stdio.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#define ERR_MGS(m) do{\
fprintf(stderr,"__%d\t__",__LINE__);\
perror(m);\
}while(0)
int do_inter(int newfd,struct sockaddr_in sind,sqlite3* db);
int import(sqlite3* db);
void handler(int arg){
while(waitpid(-1,NULL,WNOHANG)>0);
}
int main(int argc, const char *argv[])
{
//打开数据库
sqlite3 *db;
if(sqlite3_open("./sq.db",&db)!=0){
fprintf(stderr,"line:%d sqlite3_open:%s\n",__LINE__,sqlite3_errmsg(db));
fprintf(stderr,"line:%d sqlite3_open:%d\n",__LINE__,sqlite3_errcode(db));
return 0;
}
printf("打开数据库成功\n");
//将文件导入数据库
import(db);
//用信号函数循环回收僵尸进程,为下面使用多进程并发服务器做铺垫
__sighandler_t s=signal(17,handler);
if(SIG_ERR==s){
ERR_MGS("signal");
return 0;
}
//创建套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(-1==sfd){
ERR_MGS("socket");
return 0;
}
//允许端口快速重用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))<0)
{
ERR_MGS("setsockopt");
return -1;
}
//将ip和端口号绑定在套接字上
//定义地址族变量
struct sockaddr_in sin;
//填充地址信息结构体
sin.sin_family=AF_INET;
sin.sin_port=htons(8888);
sin.sin_addr.s_addr=inet_addr("192.168.8.214");
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){
ERR_MGS("bind");
return 0;
}
//将套接字设置为被动监听状态
if(listen(sfd,88)<0){
ERR_MGS("listen");
return 0;
}
//定义结构体变量和其他变量用于下面的逻辑
struct sockaddr_in sind;
socklen_t addrlen=sizeof(sind);
pid_t pid;
int newfd;
//使用多进程并发服务器实现多个客户端同时在线
while(1){
//父进程循环连接客户端
newfd=accept(sfd,(struct sockaddr*)&sind,&addrlen);
if(newfd<0){
ERR_MGS("accept");
return 0;
}
printf("[%s %d] newfd=%d\n",inet_ntoa(sind.sin_addr),ntohs(sind.sin_port),newfd);
if((pid=fork())==0){
//关闭无用的文件描述符
close(sfd);
//调用交互函数
do_inter(newfd,sind,db);
//退出进程
exit(0);
}else if(pid>0){
close(newfd);
}else{
ERR_MGS("fork");
return 0;
}
}
return 0;
}
//导入数据库
int import(sqlite3* db){
//打开要导入的文件
FILE* fd=fopen("../dict.txt","r");
if(fd<0){
perror("open");
return 0;
}
printf("打开文件成功\n");
//创建一张表格
char c[128]="create table if not exists stu3(name char,chinese char)";
char *errmsg=NULL;
if(sqlite3_exec(db,c,NULL,NULL,&errmsg)){
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
return 0;
}
printf("创建成功\n");
char chinese[200]="";
char name[128]="";
char buf[300]="";
char d[500]="";
//将文件中的数据储存到name和chinese中;
while(fgets(buf,sizeof(buf),fd)!=NULL){
char* p=buf;
while(1){
if(*p!=' ' || (*p != ' ' && *(p+1) != ' ')){
p++;
}else {
break;
}
}
*p='\0';
p++;
strcpy(name,buf);
while(*p==' '){
p++;
}
strcpy(chinese,p);
//循环存入到数据库中
sprintf(d,"insert into stu3 values(\"%s\",\"%s\");",name,chinese);
if(sqlite3_exec(db,d,NULL,NULL,&errmsg)!=0){
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
return 0;
}
bzero(d,sizeof(d));
bzero(buf,sizeof(buf));
bzero(name,sizeof(name));
bzero(chinese,sizeof(chinese));
}
printf("数据导入完成.....\n");
}
//与客户端交互
int do_inter(int newfd,struct sockaddr_in sind,sqlite3* db){
char buf[256]="";
char bbuf[256]="";
char name2[128]="";
char name3[128]="";
//接收客户端信息
ssize_t res,red;
int falg=0;
int fad=0;
int std=0;
//定义数据库需要的变量
int line;
int list;
char **ptr;
umask(0);
while(1){
FILE* fd=fopen("hello.txt","r+");
if(fd<0){
ERR_MGS("fopen");
return 0;
}
DNG:
SND:
FSP:
bzero(buf,sizeof(buf));
bzero(bbuf,sizeof(bbuf));
res=recv(newfd,buf,sizeof(buf),0);
if(0==res)
{
if(buf[0]=='Q'){
char bsp[128]="";
sprintf(bsp,"delete from stu5 where name=\"%s\";",buf+1);
char* errmsg=NULL;
if(sqlite3_exec(db,bsp,NULL,NULL,&errmsg)!=0){
printf("line: %d sqlite3_close :%s\n",\
__LINE__,errmsg);
return 0;
}
printf("delete success\n");
printf("用户%s已退出\n",buf+1);
goto DNG;
}
}else if(-1==res){
ERR_MGS("recv");
return 0;
}
//退出逻辑
if(buf[0]=='Q'){
printf("--%d--\n",__LINE__);
char bsp[128]="";
char fdd[128]="";
char spp[128]="";
res=recv(newfd,fdd,sizeof(fdd),0);
if(-1==res){
ERR_MGS("recv");
return 0;
}
strcpy(spp,buf+1);
strcat(spp,fdd);
sprintf(bsp,"delete from stu5 where name=\"%s\";",spp);
char* errmsg=NULL;
if(sqlite3_exec(db,bsp,NULL,NULL,&errmsg)!=0){
printf("line: %d sqlite3_close :%s\n",\
__LINE__,errmsg);
return 0;
}
printf("delete success\n");
printf("用户%s已退出\n",buf+1);
goto DNG;
}
//注册逻辑
if(buf[0]=='Z'){
int pdd=fseek(fd,0,SEEK_SET);
while(1){
falg=0;
red=fscanf(fd,"%s",bbuf);
if(red<0){
printf("文件校验完毕\n");
break;
}
if(strcmp(bbuf,buf+1)==0){
bzero(bbuf,sizeof(bbuf));
strcpy(bbuf,"The user name exists");
if(send(newfd,bbuf,sizeof(bbuf),0)<0){
ERR_MGS("send");
break;
}
falg=1;
break;
}
}
if(falg==0){
fseek(fd,0,SEEK_END);
fprintf(fd,"%s\n",buf+1);
fflush(fd);
bzero(bbuf,sizeof(bbuf));
strcpy(bbuf,"Registration Successful");
if(send(newfd,bbuf,sizeof(bbuf),0)<0){
ERR_MGS("send");
break;
}
}
fclose(fd);
}
//登录逻辑
if(buf[0]=='D'){
fad=0;
int add=fseek(fd,0,SEEK_SET);
printf("%d\n",add);
while(1){
fad=0;
red=fscanf(fd,"%s",bbuf);
if(red<0){
printf("文件校验完毕\n");
break;
}
if(strcmp(bbuf,buf+1)==0){
printf("该用户存在\n");
fad=1;
break;
}
}
if(fad==1){
//创建一张表格
char c[128]="create table if not exists stu5(name char primary key)";
char *errmsg=NULL;
if(sqlite3_exec(db,c,NULL,NULL,&errmsg)){
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
return 0;
}
printf("创建成功\n");
}
while(1){
falg=0;
//查找表格中是否有登录信息
char cd[128]="select* from stu5";
char *errmsg=NULL;
if(sqlite3_get_table(db,cd,&ptr,&line,&list,&errmsg)!=0){
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
return 0;
}
for(int i=0;i<(line+1)*list;i++){
if(strcmp(ptr[i],buf+1)==0){
bzero(bbuf,sizeof(bbuf));
strcpy(bbuf,"User logged in");
if(send(newfd,bbuf,sizeof(bbuf),0)<0){
ERR_MGS("send");
break;
}
falg=1;
goto SND;
}
}
//将登录信息插入到表格中去
if(falg==0){
bzero(cd,sizeof(cd));
sprintf(cd,"insert into stu5 values(\"%s\")",buf+1);
if(sqlite3_exec(db,cd,NULL,NULL,&errmsg)!=0){
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
return 0;
}
printf("登录信息插入表格成功\n");
bzero(bbuf,sizeof(bbuf));
strcpy(bbuf,"Login successfully");
if(send(newfd,bbuf,sizeof(bbuf),0)<0){
ERR_MGS("send");
break;
}
goto DNG;
}
}
}
bzero(bbuf,sizeof(bbuf));
strcpy(bbuf,"The user does not exist");
if(send(newfd,bbuf,sizeof(bbuf),0)<0){
ERR_MGS("send");
break;
}
fclose(fd);
}
//查单词逻辑
if(buf[0]=='C'){
res=recv(newfd,name2,sizeof(name2),0);
if(0==res){
printf("用户已退出\n");
return 0;
}else if(-1==res){
ERR_MGS("recv");
return 0;
}
char fu[128]="";
sprintf(fu,"select* from stu3 where name=\"%s\";",buf+1);
char** ptr;
int row,nom;
char* errmsg=NULL;
if(sqlite3_get_table(db,fu,&ptr,&row,&nom,&errmsg)!=0){
printf("line: %d sqlite3_close :%s\n",\
__LINE__,errmsg);
bzero(fu,sizeof(fu));
strcpy(fu,"The word does not exist");
if(send(newfd,fu,sizeof(fu),0)<0){
ERR_MGS("send");
return 0;
}
goto FSP;
}
printf("updata success\n");
bzero(fu,sizeof(fu));
strcpy(fu,ptr[2]);
strcat(fu," ");
strcat(fu,ptr[3]);
if(send(newfd,fu,sizeof(fu),0)<0){
ERR_MGS("send");
return 0;
}
//创建一张表格用来储存历史信息
char bpf[256]="";
if(std==0){
strcpy(bpf,"create table if not exists stu4(name char,word char,time char)");
if(sqlite3_exec(db,bpf,NULL,NULL,&errmsg)){
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
return 0;
}
printf("创建成功\n");
std=1;
}
//获取时间
time_t t,t1;
t1=time(&t);
struct tm* info=NULL;
info=localtime(&t1);
char time[256]="";
strftime(time,sizeof(time),"%Y-%m-%d %H:%M:%S",info);
//将历史信息插入到数据库中
bzero(bpf,sizeof(bpf));
sprintf(bpf,"insert into stu4 values(\"%s\",\"%s\",\"%s\")",name2,fu,time);
if(sqlite3_exec(db,bpf,NULL,NULL,&errmsg)!=0){
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,sqlite3_errmsg(db));
fprintf(stderr,"line:%d sqlite3_exec:%d\n",__LINE__,sqlite3_errcode(db));
return 0;
}
printf("历史信息插入表格成功\n");
}
//查历史记录逻辑
if(buf[0]=='H'){
//查询表格中对应姓名的历史记录
char fu[512]="";
sprintf(fu,"select* from stu4 where name=\"%s\";",buf+1);
char** ptr;
int row,nom;
char* errmsg=NULL;
if(sqlite3_get_table(db,fu,&ptr,&row,&nom,&errmsg)!=0){
printf("line: %d sqlite3_close :%s\n",\
__LINE__,errmsg);
}
printf("updata success\n");
int i;
for(i=nom;i<(row+1)*nom;i+=nom){
printf("111\n");
bzero(fu,sizeof(fu));
strcpy(fu,ptr[i]);
strcat(fu," ");
strcat(fu,ptr[i+1]);
fu[strlen(fu)-1]='\0';
strcat(fu," ");
strcat(fu,ptr[i+2]);
printf("%s\n",fu);
if(send(newfd,fu,sizeof(fu),0)<0){
ERR_MGS("send");
return 0;
}
}
bzero(fu,sizeof(fu));
strcpy(fu,"-1");
if(send(newfd,fu,sizeof(fu),0)<0){
ERR_MGS("send");
return 0;
}
printf("查询完成\n");
}
}
//客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#define ERR_MGS(m)do{\
fprintf(stderr,"%d\n",__LINE__);\
perror(m);\
}while(0)
int scoketd;
char name1[128]="";
char paw1[128]="";
void do_find(int scoketd,char* name1);
void do_past(int scoketd,char* name1);
void handler(int arg){
char pass[128]="";
pass[0]='Q';
strcat(pass,name1);
strcat(pass,paw1);
int rad=send(scoketd,pass,sizeof(pass),0);
if(rad<0){
ERR_MGS("send");
return ;
}
kill(0,9);
}
int main(int argc, const char *argv[])
{
//基于TCP的客户端模型
//创建一个信号函数用来捕捉二号信号
__sighandler_t s=signal(2,handler);
if(SIG_ERR==s){
ERR_MGS("signal");
return 0;
}
//创建套接字
scoketd=socket(AF_INET,SOCK_STREAM,0);
if(-1==scoketd){
ERR_MGS("scoket");
return 0;
}
//允许端口快速重用
int reuse = 1;
if(setsockopt(scoketd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))<0)
{
ERR_MGS("setsockopt");
return -1;
}
printf("创建套接字成功\n");
//连接到服务器
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(8888);
sin.sin_addr.s_addr=inet_addr("192.168.8.214");
socklen_t addrlen1=sizeof(sin);
int fpd=connect(scoketd,(struct sockaddr*)&sin,addrlen1);
if(-1==fpd){
ERR_MGS("connect");
return 0;
}
printf("连接服务器成功\n");
//定义菜单需要的的变量
int num;
char name[128]="";
char paw[128]="";
char pass[256]="";
ssize_t rad;
SFD:
//登录菜单
while(1){
system("clear");
printf("<<<欢迎使用电子词典>>>\n");
printf("**********************\n");
printf("*********1.注册********\n");
printf("*********2.登录********\n");
printf("*********3.退出********\n");
printf("***********************\n");
printf("请输入您要选择的功能\n");
scanf("%d",&num);
while(getchar()!=10);
switch(num){
//注册
case 1:
bzero(name,sizeof(name));
bzero(paw,sizeof(paw));
bzero(pass,sizeof(pass));
pass[0]='Z';
printf("请输入要注册的用户名\n");
scanf("%s",name);
while(getchar()!=10);
printf("请输入要注册的密码\n");
scanf("%s",paw);
while(getchar()!=10);
strcpy(pass+1,name);
strcat(pass,paw);
rad=send(scoketd,pass,sizeof(pass),0);
if(rad<0){
ERR_MGS("send");
return 0;
}
bzero(pass,sizeof(pass));
if(recv(scoketd,pass,sizeof(pass),0)<0){
ERR_MGS("recv");
return 0;
}
if(strcmp(pass,"Registration Successful")==0){
printf("注册成功\n");
}else if(strcmp(pass,"The user name exists")==0){
printf("用户名已存在\n");
}
break;
//登录
case 2:
bzero(name,sizeof(name));
bzero(paw,sizeof(paw));
bzero(pass,sizeof(pass));
pass[0]='D';
printf("请输入用户名\n");
scanf("%s",name);
while(getchar()!=10);
strcpy(name1,name);
printf("请输入密码\n");
scanf("%s",paw);
strcpy(paw1,paw);
while(getchar()!=10);
strcpy(pass+1,name);
strcat(pass,paw);
rad=send(scoketd,pass,sizeof(pass),0);
if(rad<0){
ERR_MGS("send");
return 0;
}
bzero(pass,sizeof(pass));
if(recv(scoketd,pass,sizeof(pass),0)<0){
ERR_MGS("recv");
return 0;
}
if(strcmp(pass,"User logged in")==0){
printf("该用户已登录,登录失败\n");
}else if(strcmp(pass,"Login successfully")==0){
printf("登录成功\n");
goto PDD;
}else{
printf("该用户不存在\n");
}
break;
//退出
case 3:
goto END;
break;
default:
printf("输入错误请重新输入\n");
break;
}
printf("按下任意字符清屏\n");
while(getchar()!=10);
}
//二级菜单
while(1){
PDD:
system("clear");
printf("*****欢迎使用电子词典******\n");
printf("*******1.查单词***********\n");
printf("*******2.查历史记录*******\n");
printf("*******3.返回上级菜单*******\n");
printf("**************************\n");
printf("请输入您要选择的功能\n");
scanf("%d",&num);
while(getchar()!=10);
switch(num){
case 1:
//查单词
do_find(scoketd,name1);
break;
case 2:
//查历史记录
do_past(scoketd,name1);
break;
case 3:
//返回之前给服务器发一个信号,代表用户已经退出了
bzero(pass,sizeof(pass));
pass[0]='Q';
strcat(pass,name1);
if(send(scoketd,pass,sizeof(pass),0)<0){
ERR_MGS("send");
return 0;
}
if(send(scoketd,paw1,sizeof(paw1),0)<0){
ERR_MGS("send");
return 0;
}
//返回上级菜单
goto SFD;
break;
default:
break;
}
printf("按下任意字符清屏\n");
while(getchar()!=10);
}
END:
//关闭文件描述符
close(scoketd);
return 0;
}
//查单词
void do_find(int scoketd,char* name1){
char buf[256]="";
int rad;
while(1){
bzero(buf,sizeof(buf));
printf("请输入您要查的单词或按#退出\n");
buf[0]='C';
scanf("%s",buf+1);
getchar();
if(strcmp(buf+1,"#")==0){
break;
}
rad=send(scoketd,buf,sizeof(buf),0);
if(rad<0){
ERR_MGS("send");
return ;
}
rad=send(scoketd,name1,strlen(name1),0);
if(rad<0){
ERR_MGS("send");
return ;
}
bzero(buf,sizeof(buf));
if(recv(scoketd,buf,sizeof(buf),0)<0){
ERR_MGS("recv");
return ;
}
if(strcmp(buf,"The word does not exist")==0){
printf("未查询到该单词\n");
}else{
printf("%s",buf);
}
}
}
//查历史记录
void do_past(int scoketd,char* name1){
char buf[512]="";
buf[0]='H';
strcat(buf,name1);
int rad=send(scoketd,buf,sizeof(buf),0);
if(rad<0){
ERR_MGS("send");
return ;
}
bzero(buf,sizeof(buf));
while(1){
if(recv(scoketd,buf,sizeof(buf),0)>0){
if(strcmp(buf,"-1")==0){
break;
}
}
printf("%s\n",buf);
bzero(buf,sizeof(buf));
}
printf("信息查询完毕,输入任意字符退出查询\n");
while(getchar()!=10);
}