云词典项目流程图
执行效果参考
服务器
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <signal.h>
#include <sqlite3.h>
#include <sys/wait.h>
#include <poll.h>
#include <time.h>
#include "head.h"
char *err=NULL;
int zhuce(MSG xie,int ept,sqlite3 *db,struct sockaddr_in addr);//注册
int denglu(MSG xie,int ept,sqlite3 *db);//登录
int danci(MSG xie,int ept,sqlite3 *db);//查询
int lishi(MSG xie,int ept,sqlite3 *db);//历史记录
int main(int argc, char const *argv[])
{
if (argc<2)
{
printf("usage:<port>");
return -1;
}
//打开或创建数据库
sqlite3 *db=NULL;
if (sqlite3_open("./cidian.db", &db)!=SQLITE_OK)
{
printf("sqlite3_open err:%s\n",sqlite3_errmsg(db));
return -1;
}
printf("词典数据库打开成功。\n");
//创建套接字 用于链接
int sock=socket(AF_INET,SOCK_STREAM,0);
if (sock<0)
{
perror("socket err");
return -1;
}
printf("sock:%d\n",sock);
//绑定
struct sockaddr_in add,addr;
socklen_t len=sizeof(addr);
add.sin_family=AF_INET; //协议族AF_INET
add.sin_port=htons(atoi(argv[1])); //端口
#if 1
add.sin_addr.s_addr=inet_addr("0.0.0.0");//ip地址转换为32位无符号长整数型数
#else
add.sin_addr.s_addr=INADDR_ANY;
#endif
if (bind(sock,(struct sockaddr *)&add,sizeof(add)) < 0 )
{
perror("bind err.");
return -1;
}
printf("bind success\n");
//监听
if ( listen(sock,6) < 0 )
{
perror("listen err");
return -1;
}
printf("listen success\n");
//引入poll 创建表
int last=-1;
struct pollfd pofd[128];
//填数据
pofd[++last].fd=sock;
pofd[last].events=POLLIN;
//协议
MSG xie;
while (1)
{
//监测
if (poll(pofd,last+1,-1) < 0)
{
perror("poll err.");
return -1;
}
//判断
for (int i = 0; i <= last; i++)
{
if (pofd[i].revents == POLLIN)
{
if (pofd[i].fd == sock )//判断链接
{
int ept=accept(sock,(struct sockaddr *)&addr,&len);
if (ept < 0)
{
perror("accept err.");
return -1;
}
printf("accept:%d ",ept);
printf("ip:%s port:%d\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
pofd[++last].fd=ept;
pofd[last].events=POLLIN;
}
else//接收
{
int ret=recv(pofd[i].fd,&xie,sizeof(xie),0);
if (ret<0)
{
perror("recv err.");
return -1;
}
else if(ret==0)//有客户端退出
{
printf("ip:%s port:%d 已退出\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
close(pofd[i].fd);
pofd[i--]=pofd[last--];//删除退出客户端
}
else//接收到数据
{
switch (xie.type)
{
case R :zhuce(xie,pofd[i].fd,db,addr);break;//注册
case L :denglu(xie,pofd[i].fd,db);break; //登录
case Q :danci(xie,pofd[i].fd,db);break; //单词查询
case H :lishi(xie,pofd[i].fd,db);break; //历史记录
default:printf("输入错误啦\n");break;
}
}
}
}
}
}
return 0;
}
//注册
int zhuce(MSG xie,int ept,sqlite3 *db,struct sockaddr_in addr)
{
char **result=NULL,sql[128]={0};
int hang,lie,k=0;
sqlite3_get_table(db,"select * from zhuce;",&result,&hang,&lie,&err);//查询表中数据
for (int i = 0; i <= hang; i++)//遍历行
{
if (strcmp(xie.name,result[k])==0)//判断表中帐号是否存在
{
strcpy(xie.data,"already exist!!!");
send(ept,&xie,sizeof(xie),0);
return 0;
}
else
{
k+=2;//k移到下一行
}
}
if (strncmp(xie.data,"already exist!!!",17)!=0)//表中帐号不存在注册
{
sprintf(sql,"insert into zhuce values(\"%s\",\"%s\");",xie.name,xie.data);//拼接指令
if(sqlite3_exec(db,sql,NULL,NULL,&err)!=SQLITE_OK)//往表中写入内容
{
printf("insert zhuce err:%s\n",err);
return -1;
}
//通知用户注册成功
strcpy(xie.data,"OK");
send(ept,&xie,sizeof(xie),0);
printf("ip:%s port:%d name:%s 注册成功!\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port),xie.name);
}
return 0;
}
//登录
int denglu(MSG xie,int ept,sqlite3 *db)
{
char **result=NULL;
char sql[128]={0};
int hang,lie,k=0;
sqlite3_get_table(db,"select * from zhuce;",&result,&hang,&lie,&err);//查询表中数据
for (int i = 0; i <= hang; i++)
{
if ((strcmp(xie.name,result[k])==0)&&(strcmp(xie.data,result[k+1])==0))
{
strcpy(xie.data,"OK");
send(ept,&xie,sizeof(xie),0);
return 0;
}
k+=2;//k移到下一行
}
strcpy(xie.data,"err.");
send(ept,&xie,sizeof(xie),0);
return 0;
}
//查询单词
int danci(MSG xie,int ept,sqlite3 *db)
{
char **result=NULL,sql[128]={0};
int hang,lie,k=0,n=0;
sqlite3_get_table(db,"select * from cidian;",&result,&hang,&lie,&err);//查询表中数据
for (int i = 0; i <=hang; i++)
{
if (strcmp(xie.data,result[k])==0)//判断单词是否存在
{
//往历史记录表中写入时间
char buf[128];
time_t tv;
struct tm *timer;
tv = time(&tv);
timer = localtime(&tv);
strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S", timer);
sprintf(sql,"insert into lishi values(\"%s\",\"%s\",\"%s\");",xie.name,buf,xie.data);//拼接指令
if(sqlite3_exec(db,sql,NULL,NULL,&err)!=SQLITE_OK)//写入数据库内容
{
printf("insert lishi err:%s\n",err);
return -1;
}
//发送释义并退出
strcpy(xie.data,result[++k]);
send(ept,&xie,sizeof(xie),0);
return 0;
}
else
{
for (int j = 0; j < lie; j++)//不存在k移到下一行
{
k++;
}
}
}
//没有给客户端提示
strcpy(xie.data,"没有收录!");
send(ept,&xie,sizeof(xie),0);
return 0;
}
//查询历史
int lishi(MSG xie,int ept,sqlite3 *db)
{
char **result=NULL,sql[128]={0};
int hang,lie,k=0,l=0;
strcpy(sql,"select * from lishi;");
sqlite3_get_table(db,sql,&result,&hang,&lie,&err);//查询表中数据
for (int i = 0; i <=hang; i++)
{
if (strcmp(xie.name,result[k])==0)//根据帐号查找历史记录
{
sprintf(xie.data,"%s : %s",result[k+1],result[k+2]);//result[++k],result[++k]有可能造成内容相同!!
send(ept,&xie,sizeof(xie),0);
l=1;//用作判断是否有记录
}
k+=3;//不同k移到下一行
}
//提示发送结束或没有
if (l==1)
{
strcpy(xie.data,"OK");
send(ept,&xie,sizeof(xie),0);
}
else
{
l=0;
strcpy(xie.data,"无历史记录!");
send(ept,&xie,sizeof(xie),0);
}
return 0;
}
客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "head.h"
char name[128]={0};
void caidan1();//一级菜单
void caidan2();//二级菜单
int zhuce(MSG xie,int sock);//注册
int denglu(MSG xie,int sock);//登录
int danci(MSG xie,int sock);//查询
int lishi(MSG xie,int sock);//退出
int main(int argc, char const *argv[])
{
if (argc<3)
{
printf("usage:<ip> <port>");
return -1;
}
//创建套接字 用于链接
int sock=socket(AF_INET,SOCK_STREAM,0);
if (sock<0)
{
perror("socket err");
return -1;
}
printf("sock:%d\n",sock);
//连接服务器
struct sockaddr_in add;
socklen_t len=sizeof(add); //填充的结构体的大小
add.sin_family=AF_INET; //协议族AF_INET
add.sin_port=htons(atoi(argv[2])); //端口
add.sin_addr.s_addr=inet_addr(argv[1]); //ip地址转换为32位无符号长整数型数
if (connect(sock,(struct sockaddr *)&add,len)< 0)
{
perror("connect err");
return -1;
}
printf("connect success.\n");
// printf("请输入选项:");
MSG xie;//协议
int A;
while (1)
{
A=0;//选项
caidan1();
scanf("%d",&A);
getchar();
switch (A)
{
case 1:zhuce(xie,sock);break;//注册
case 2: if (denglu(xie,sock)==1)goto next;else{break;}//登录
case 3:close(sock);exit(0);break;//退出
default:printf("输入错误啦\n");break;
}
}
next:
while (1)
{
A=0;//选项
caidan2();
scanf("%d",&A);
getchar();
switch (A)
{
case 1:danci(xie,sock);break;//查询
case 2:lishi(xie,sock);break;//历史记录
case 3:close(sock);exit(0);break;//退出
default:printf("输入错误啦\n");break;
}
}
close(sock);
return 0;
}
//登录菜单
void caidan1()
{
printf("************************************\n");
printf(" * *\n");
printf(" * 《大威天龙云词典》 *\n");
printf(" * *\n");
printf(" * 1:注册 2:登录 3:退出 *\n");
printf(" * *\n");
printf("************************************\n");
printf("请输入选项:");
}
//查询菜单
void caidan2()
{
printf("*************************************\n");
printf(" * *\n");
printf(" * 《大威天龙云词典》 *\n");
printf(" * *\n");
printf(" * 1:查询 2:历史记录 3:退出 *\n");
printf(" * *\n");
printf("*************************************\n");
printf("请输入选项:");
}
//用户注册
int zhuce(MSG xie,int sock)
{
xie.type=R;
printf("请输入账号:");
fgets(xie.name,sizeof(xie.name),stdin);
if (xie.name[strlen(xie.name)-1]=='\n')
xie.name[strlen(xie.name)-1]='\0';
printf("请输入密码:");
fgets(xie.data,sizeof(xie.data),stdin);
if (xie.data[strlen(xie.data)-1]=='\n')
xie.data[strlen(xie.data)-1]='\0';
send(sock,&xie,sizeof(xie),0);
recv(sock,&xie,sizeof(xie),0);
printf("%s\n\n",xie.data);
return 0;
}
//用户登录
int denglu(MSG xie,int sock)
{
xie.type=L;
printf("请输入账号:");
fgets(xie.name,sizeof(xie.name),stdin);
if (xie.name[strlen(xie.name)-1]=='\n')
xie.name[strlen(xie.name)-1]='\0';
strcpy(name,xie.name);//保存帐号,用于后期插入历史记录
printf("请输入密码:");
fgets(xie.data,sizeof(xie.data),stdin);
if (xie.data[strlen(xie.data)-1]=='\n')
xie.data[strlen(xie.data)-1]='\0';
send(sock,&xie,sizeof(xie),0);
recv(sock,&xie,sizeof(xie),0);
if (strncmp(xie.data,"OK",3)==0)
{
printf("登录成功\n\n");
return 1;
}
else
{
printf("账号或密码错误!\n\n");
return 0;
}
}
//查询单词
int danci(MSG xie,int sock)
{
xie.type=Q;
while (1)
{
strcpy(xie.name,name);//防止传输协议结构体中name数据丢失
printf("\n要查询的单词(输入 # 退出):");
fgets(xie.data,sizeof(xie.data),stdin);
if (xie.data[strlen(xie.data)-1]=='\n')
xie.data[strlen(xie.data)-1]='\0';
if (strncmp(xie.data,"#",2)==0)
{
break;
}
send(sock,&xie,sizeof(xie),0);
recv(sock,&xie,sizeof(xie),0);
printf("\n释义:%s\n",xie.data);
//if (strcmp(xie.data,"没有收录!")==0)
//{
// break;
//}
}
return 0;
}
//查询历史
int lishi(MSG xie,int sock)
{
int rec;
xie.type=H;
strcpy(xie.name,name);//防止传输协议结构体中name数据丢失
send(sock,&xie,sizeof(xie),0);
putchar(10);
while (recv(sock,&xie,sizeof(xie),0))
{
if (strncmp(xie.data,"OK",3)==0)//判断传输完历史记录
{
putchar(10);
return 0;
}
if(strcmp(xie.data,"无历史记录!")==0)//判断有无历史记录
{
printf("%s\n",xie.data);
return 0;
}
printf("%s\n",xie.data);
}
return 0;
}
Makefile
all:
gcc fuTCPfuTCP.c -lsqlite3 -o f
gcc keTCP.c -o k
clean:
rm f k
txt索引导入数据库以及创建表代码
#include <stdio.h>
#include <sqlite3.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
char *err=NULL;
int cidian(sqlite3 *db);//词典
int zhuce(sqlite3 *db);//创建注册表
int lishi(sqlite3 *db);//创建历史记录表
int main(int argc, char const *argv[])
{
//打开或创建数据库
sqlite3 *db=NULL;
if (sqlite3_open("./cidian.db", &db)!=SQLITE_OK)
{
printf("sqlite3_open err:%s\n",sqlite3_errmsg(db));
return -1;
}
printf("数据库打开成功。\n");
cidian(db);
zhuce(db);
lishi(db);
return 0;
}
//词典
int cidian(sqlite3 *db)
{
//打开文件
FILE *fop1=fopen("dict.txt","r");
if (fop1<0)
{
perror("fopen1 err.");
return -1;
}
//创建表
if(sqlite3_exec(db,"create table cidian(单词 char,解释 char);",NULL,NULL,&err)!=SQLITE_OK)
{
printf("create err:%s\n",err);
}
printf("数据库创建成功。\n");
//向表中插入数据
char ci[1024]={0},jie[1024]={0},sql[1024]={0};
char *p=NULL;
int n,nn=1;
while (fgets(ci,sizeof(ci),fop1)!=NULL)//每次读取一行
{
n=0;
p=strtok(ci," ");//遇到空格就分割单词,并获取单词
//获取剩余单词
while (p)//跳过单词,拼接释义
{
if (n==1)
{
strcat(jie,p);
strncat(jie," ",1);
}
n=1;
p=strtok(NULL," ");//获取单词
}
sprintf(sql,"insert into cidian values(\"%s\",\"%s\");",ci,jie);//拼接指令
if(sqlite3_exec(db,sql,NULL,NULL,&err)!=SQLITE_OK)//写入数据库内容
{
printf("insert err:%s\n",err);
return -1;
}
bzero(jie,sizeof(jie));
printf("%d ",nn++);//计算行数
}
fclose(fop1);
return 0;
}
//注册
int zhuce(sqlite3 *db)
{
//创建表
if(sqlite3_exec(db,"create table zhuce(帐号 char,密码 char);",NULL,NULL,&err)!=0)
{
printf("create err:%s\n",err);
}
printf("create success\n");
//向表中插入数据
if(sqlite3_exec(db,"insert into zhuce values(\"1\",\"1\");",NULL,NULL,&err)!=0)//提前插入内容防止查询出错
{
printf("insert err:%s\n",err);
return -1;
}
printf("添加成功\n");
return 0;
}
//历史
int lishi(sqlite3 *db)
{
//创建表
if(sqlite3_exec(db,"create table lishi(帐号 char,时间 char,单词 char);",NULL,NULL,&err)!=0)
{
printf("create err:%s\n",err);
}
printf("create success\n");
//向表中插入数据
if(sqlite3_exec(db,"insert into lishi values(\"1\",\"1\",\"1\");",NULL,NULL,&err)!=0)//提前插入内容防止查询出错
{
printf("insert err:%s\n",err);
return -1;
}
printf("添加成功\n");
return 0;
}
注意
导入代码运行时间较长!!!
数字是行数!!