16. 电子词典项目需求
项目要求:
- 登录注册功能,不能重复登录,重复注册
- 单词查询功能
- 历史记录功能,存储单词,意思,以及查询时间
- 基于TCP,支持多客户端连接
- 采用数据库保存用户信息与历史记录
- 将dict.txt的数据导入到数据库中保存。
- 按下ctrl+c退出客户端后,注销该客户端的登录信息
格式要求:
- main函数只跑逻辑,不允许跑功能代码
- 功能代码封装成函数
- 先分析需求
- 将上述需求用流程图画出来
- 根据流程图搭建代码框架
- 一个功能一个功能实现
流程图:
http://t.csdn.cn/ScQSW
网络编程电子词典项目:
目录
项目要求:
格式要求:
流程图:
服务器代码
客户端
实现效果
服务器代码
头文件
#ifndef __FUNC_H__
#define __FUNC_H__
#include <sqlite3.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <signal.h>
#include <time.h>
#define PORT 6666
#define IP "192.168.100.17"
typedef void (*sighandler_t)(int);
#define ERR_MSG(msg) do{\
fprintf(stderr,"line:__%d__\n",__LINE__);\
perror(msg);\
}while(0)
struct msg{
char type; //消息类型
char name[128]; //名字
char password[128]; //密码
char word[128]; //单词
char trans[128]; //翻译
char time[256]; //时间
}sermsg;
sqlite3* sqlite3_database(); //创建数据库表
int cli_net(); //创建套接字.链接客户端.绑定信息结构体
int sqlite3_close(sqlite3* db); //关闭数据库
int sqlite3_word(sqlite3* db); //导入单词函数
int sqlite3_worddelete(sqlite3 *db); //删除单词表函数
int ser_recv(int newfd,struct sockaddr_in cin); //接收函数
int do_login(int newfd); //登录函数
int do_register(int newfd); //注册函数
int do_find(int newfd); //查询单词
int do_history(int newfd); //查询历史记录
int do_quit(int newfd); //退出
void handler(int sig); //捕获僵尸进程
#endif
功能文件
#include "01_serfunc.h"
sqlite3 *db=NULL;
char *errmsg=NULL;
sqlite3* sqlite3_database()
{
//创建并打开一个数据库
if(sqlite3_open("./word.db",&db)!=SQLITE_OK)
{
fprintf(stderr,"line:%d sqlite3_open failed:%d:%s\n",\
__LINE__,sqlite3_errcode(db),sqlite3_errmsg(db));
return NULL;
}
printf("sqlite3_open success\n");
//删除单词表
sqlite3_worddelete(db);
//创建一张表格,数据库中sql怎么写就怎么写
char sql[128]="create table if not exists wordbase(word char,explain char);";
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return NULL;
}
printf("table stu create success\n");
//创建一张表格 用于保存用户注册信息
bzero(sql,sizeof(sql));
sprintf(sql,"create table if not exists userbase(user char primary key,password char);");
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return NULL;
}
printf("table userbase create success\n");
//创建一张表格 用于存储用户登录信息
bzero(sql,sizeof(sql));
sprintf(sql,"create table if not exists recordbase(user char primary key);");
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return NULL;
}
printf("table recordbase create success\n");
//创建一张表格 用于存储用户历史查询信息
bzero(sql,sizeof(sql));
sprintf(sql,"create table if not exists historybase(user char,word char,trans char,time char);");
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return NULL;
}
printf("table historybase create success\n");
//导入单词函数
sqlite3_word(db);
return db;
}
int sqlite3_close(sqlite3* db) //关闭数据库
{
//关闭数据库
if(sqlite3_close(db)!=SQLITE_OK)
{
fprintf(stderr,"line:%d sqlite3_close failed:%d:%s\n",\
__LINE__,sqlite3_errcode(db),sqlite3_errmsg(db));
return-1;
}
return 0;
}
int sqlite3_word(sqlite3 *db) //导入单词函数
{
//打开一个文件
FILE *fd=fopen("./dict.txt","r");
if(NULL==fd)
{
perror("fopen");
return -1;
}
printf("电子词典正在导入请稍后>>>\n");
//指定的文件中格式化获取数据
//存储每一行数据
char buf[512]="";
char get_word[128]="";
char get_explain[128]="";
char sql[128]="";
char *errmsg=NULL;
//循环读取每一行内容
while(1)
{
bzero(get_word,sizeof(get_word));
bzero(get_explain,sizeof(get_explain));
if(fgets(buf,sizeof(buf),fd)==NULL)
{
printf("单词导入完毕\n");
return -1;
}
buf[strlen(buf)-1]='\0';
for(int i=0;i<buf[i+2] ;i++)
{
if(buf[i]!=' ' && buf[i+1]==' ' && buf[i+2]==' ')
{
strncpy(get_word,buf,i+1);
}
else if(buf[i]==' ' && buf[i+1]==' ' && buf[i+2]!=' ')
{
strcpy(get_explain,buf+i+2);
break;
}
}
bzero(sql,sizeof(sql));
sprintf(sql,"insert into wordbase values(\"%s\",\"%s\");",get_word,get_explain);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return-1;
}
}
//关闭文件描述符
fclose(fd);
return 0;
}
int sqlite3_worddelete(sqlite3 *db) //删除单词表函数
{
char sql[128]="drop table wordbase;";
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
// fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return-1;
}
printf("worddelete success\n");
return 0;
}
int ser_recv(int fd,struct sockaddr_in cin) //接收函数
{
int newfd=fd;
ssize_t res=0;
while(1)
{
//bzero(&sermsg,sizeof(sermsg));
res=recv(newfd,&sermsg,sizeof(sermsg),0);
struct msg sermsg1;
strcpy(sermsg1.name,sermsg.name);
printf("%s\n",sermsg1.name);
if(res<0)
{
return -1;
}
else if(0==res)
{
fprintf(stderr,"[%s:%d]newfd = %d 客户端下线\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
//删除登录信息
char sql[521];
char *errmsg=NULL;
sprintf(sql,"delete from recordbase where user=\"%s\";",sermsg1.name);
//printf("%s\n",sql);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return 0;
}
return 0;
}
char choose=sermsg.type;
switch(choose)
{
case '1': //注册
do_register(newfd);
break;
case '2': //登录
do_login(newfd);
break;
case '4': //查询
do_find(newfd);
break;
case '5': //历史记录
do_history(newfd); //查询历史记录
break;
case '6': //退出
do_quit(newfd);
break;
}
}
return 0;
}
//捕获僵尸进程
void handler(int sig)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
return ;
}
int cli_net()//创建套接字.链接客户端.绑定信息结构体
{
//创建流式套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
//允许端口快速重用
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速重用\n");
//填充地址信息结构体
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)
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
//将套接字设置为监听状态
if(listen(sfd,5)<0)
{
ERR_MSG("listen");
return -1;
}
printf("listen success\n");
return sfd;
}
int do_quit(int newfd)
{
//删除登录信息
char sql[256];
char *errmsg=NULL;
sprintf(sql,"delete from recordbase where user=\"%s\";",sermsg.name);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return 0;
}
return 0;
}
int do_history(int newfd) //查询历史记录
{
//将数据包发送给客户端 根据登录名进行遍历查找记录表
char sql[256]="";
sprintf(sql,"select *from historybase where user=\"%s\";",sermsg.name);
char **pres = NULL; //存储结果
int row, column; //查询到的结果的行数;查询到的结果的列数
char* errmsg = NULL;
if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
printf("row=%d column=%d\n", row, column); //打印行和列
bzero(sermsg.name,sizeof(sermsg.name));
bzero(sermsg.word,sizeof(sermsg.word));
bzero(sermsg.trans,sizeof(sermsg.trans));
bzero(sermsg.time,sizeof(sermsg.time));
int i=0;
for(i=0; i<(row+1)*column; i++)
{
if(i%column == column-4)
sprintf(sermsg.name,"%s",pres[i]);
else if(i%column == column-3)
sprintf(sermsg.word,"%s",pres[i]);
else if(i%column == column-2)
sprintf(sermsg.trans,"%s",pres[i]);
else if(i%column == column-1)
{
sprintf(sermsg.time,"%s",pres[i]);
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
}
}
if(i==(row+1)*column)
{
sermsg.type='S'; //查询完成标注
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
}
if(i==0)
{
sermsg.type='F'; //查询完成标注
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
}
//释放内存空间
sqlite3_free_table(pres);
return 0;
}
//查询单词回调函数,满足就会执行
int find_callBack(void *arg, int column, char **column_text, char **column_name) //void* arg = &flag
{
strcat(sermsg.trans,column_text[1]);
strcat(sermsg.trans,"\n");
sermsg.type='S';
fprintf(stderr,"查询单词成功\n");
(*(int *)arg)++;
return 0;
}
int do_find(int newfd) //查询单词函数
{
//清空翻译
bzero(sermsg.trans,sizeof(sermsg.trans));
char sql[512];
char *errmsg=NULL;
int flag=0;
sprintf(sql,"select * from wordbase where word=\"%s\";",sermsg.word);
if(sqlite3_exec(db,sql,find_callBack,&flag,&errmsg)!=SQLITE_OK)
{
sermsg.type='E';
fprintf(stderr,"newfd = %d 查询单词失败\n",newfd);
//将数据包发送给客户端
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return-1;
}
if(flag==2)
{
//将数据包发送给客户端
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
}
else{
//将数据包发送给客户端
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
}
//将查询信息插入到recordbase表格中
//查询时间
time_t t1;
struct tm* timeinfo=NULL;
time(&t1);
timeinfo=localtime(&t1);
char time1[256]="";
sprintf(time1,"%d-%d-%d %d:%d:%d\n",timeinfo->tm_year+1900,timeinfo->tm_mon+1,timeinfo->tm_mday,\
timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);
//插入历史记录表
bzero(sql,sizeof(sql));
errmsg=NULL;
sprintf(sql,"insert into historybase values(\"%s\",\"%s\",\"%s\",\"%s\");",\
sermsg.name,sermsg.word,sermsg.trans,time1);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
return 0;
}
return 0;
}
int do_register(int newfd) //注册函数
{
char sql[364];
char *errmsg=NULL;
sprintf(sql,"insert into userbase values(\"%s\",\"%s\");",\
sermsg.name,sermsg.password);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
sermsg.type='E';
fprintf(stderr,"newfd = %d 注册失败\n",newfd);
//将数据包发送给客户端
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return-1;
}
sermsg.type='S';
fprintf(stderr,"newfd = %d 注册成功\n",newfd);
//将数据包发送给客户端
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
return 1;
}
//登录查询回调函数,满足就会执行
int login_callBack(void *arg, int column, char **column_text, char **column_name) //void* arg = &flag
{
if(strcmp(column_text[0],sermsg.name)==0 && strcmp(column_text[1],sermsg.password)==0)
{
sermsg.type='S';
*(int *)arg=1;
}
return 0;
}
int do_login(int newfd) //登录函数
{
char sql[512];
char *errmsg=NULL;
int flag=0;
sprintf(sql,"select * from userbase where user=\"%s\";",sermsg.name);
if(sqlite3_exec(db,sql,login_callBack,&flag,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return -1;
}
if(flag==0)
{
sermsg.type='E';
fprintf(stderr,"newfd = %d 登录失败\n",newfd);
//将数据包发送给客 户端
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
}
//说明注册信息表中有,可以登录,判断是否为登录状态
else if(flag==1)
{
//将登陆信息保存到登录信息表中
char sql[364];
char *errmsg=NULL;
sprintf(sql,"insert into recordbase values(\"%s\");",sermsg.name);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
sermsg.type='R';
fprintf(stderr,"登录重复\n");
bzero(sermsg.name,sizeof(sermsg.name));
//将数据包发送给客户端
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
return 0;
}
fprintf(stdout,"%s 登录成功\n",sermsg.name);
//设置为登录状态,登陆成功,将数据包发送给客户端
if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
{
ERR_MSG("send");
return -1;
}
}
return 0;
}
测试文件
#include "01_serfunc.h"
int main(int argc, const char *argv[])
{
//捕获僵尸进程
sighandler_t s = signal(SIGCHLD, handler);
if(SIG_ERR == s)
{
perror("signal");
return -1;
}
//创建套接字.链接客户端.绑定信息结构体
int sfd=cli_net();
//创建数据库导入单词
sqlite3*db=sqlite3_database();
//由于自动获取,只需要定义几个结构体变量进行接受,需要时直接访问里面成员即可
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
//从已经完成链接的队列头获取一个客户端的信息,
//生成一个新的文件描述符,新的才是用于和客户端通信的文件描述符
pid_t pid=0;
while(1)
{
//父进程负责处理客户连接
int newfd=accept(sfd,(struct sockaddr *)&cin,&addrlen);
if(newfd<0)
{
ERR_MSG("accept");
return -1;
}
printf("[%s:%d] newfd=%d 连接成功\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
//创建子进程
pid=fork();
if(pid==0)
{
// printf("进入接收函数\n");
close(sfd);
//接收消息
ser_recv(newfd,cin);
//退出子进程
close(newfd);
exit(0);
}
else if(pid>0)
{
// close(newfd);
}
else
{
ERR_MSG("fork");
return -1;
}
}
//关闭数据库
sqlite3_close(db);
return 0;
}
客户端
头文件
#ifndef __FUNC_H__
#define __FUNC_H__
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#define PORT 6666
#define IP "192.168.100.17"
#define ERR_MSG(msg) do{\
fprintf(stderr,"line:__%d__\n",__LINE__);\
perror(msg);\
}while(0)
struct msg{
char type; //消息类型
char name[128]; //名字
char password[128]; //密码
char word[128]; //单词
char trans[128]; //翻译
char time[256]; //时间
}climsg;
void pri_menu(); //主菜单
void sec_menu(); //查询菜单
int cli_login(int sfd); //登录
int cli_register(int sfd); //注册
int cli_find(int sfd); //查找单词
int cli_history(int sfd); //查询历史记录
int clisend(int sfd); //发送函数
int clirecv(int sfd); //接收函数
int cli_quit(int sfd); //退出函数
int net_ser(); //创建套接字.链接客户端.绑定信息结构体
#endif
功能文件
#include "02_clifunc.h"
void pri_menu() //主菜单
{
printf("------欢迎来到电子词典-----\n");
printf("--------1.注册-------------\n");
printf("--------2.登录-------------\n");
printf("--------3.退出-------------\n");
printf("---------------------------\n");
}
void sec_menu() //查询菜单
{
printf("------欢迎来到电子词典-----\n");
printf("--------4.查询单词---------\n");
printf("--------5.历史查询记录-----\n");
printf("--------6.退出-------------\n");
printf("---------------------------\n");
}
int cli_quit(int sfd) //退出
{
//封装协议
climsg.type='6';
//将数据包发送给服务器
if(send(sfd,&climsg,sizeof(climsg),0)<0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
int cli_history(int sfd)//查询历史记录
{
//封装协议
climsg.type='5';
//将数据包发送给服务器
if(send(sfd,&climsg,sizeof(climsg),0)<0)
{
ERR_MSG("send");
return -1;
}
while(1)
{
//阻塞接收服务器的回复
if(recv(sfd,&climsg,sizeof(climsg),0)<0)
{
ERR_MSG("recv");
return -1;
}
if(climsg.type=='S')
break;
if(climsg.type=='F')
{
fprintf(stdout,"没有查询记录!");
break;
}
fprintf(stdout,"%s %s %s %s\n",climsg.name,climsg.word,climsg.trans,climsg.time);
}
return 1;
}
int cli_find(int sfd) //查找单词
{
//封装协议
climsg.type='4';
printf("请输入要查询的单词>>>\n");
fgets(climsg.word,sizeof(climsg.word),stdin);
climsg.word[strlen(climsg.word)-1]=0;
//将数据包发送给服务器
if(send(sfd,&climsg,sizeof(climsg),0)<0)
{
ERR_MSG("send");
return -1;
}
//阻塞接收服务器的回复
if(recv(sfd,&climsg,sizeof(climsg),0)<0)
{
ERR_MSG("recv");
return -1;
}
if(climsg.type=='S')
{
fprintf(stderr,"%s\n",climsg.trans);
}
else if(climsg.type=='E')
{
fprintf(stderr,"查询失败,请检查单词是否正确\n");
return -1;
}
return 0;
}
int cli_login(int sfd) //登录
{
//封装协议
climsg.type='2';
printf("请输入登录用户名>>>\n");
fgets(climsg.name,sizeof(climsg.name),stdin);
climsg.name[strlen(climsg.name)-1]=0;
printf("请输入登录密码>>>\n");
fgets(climsg.password,sizeof(climsg.password),stdin);
climsg.password[strlen(climsg.password)-1]=0;
//将数据包发送给服务器
if(send(sfd,&climsg,sizeof(climsg),0)<0)
{
ERR_MSG("send");
return -1;
}
//阻塞接收服务器的回复
if(recv(sfd,&climsg,sizeof(climsg),0)<0)
{
ERR_MSG("recv");
return -1;
}
if(climsg.type=='S')
{
fprintf(stderr,"登录成功\n");
return 1;
}
else if(climsg.type=='E')
{
fprintf(stderr,"登录失败,请检查密码或者先注册\n");
return -1;
}
else if(climsg.type=='R')
{
fprintf(stderr,"重复登录\n");
return -1;
}
return 1;
}
int cli_register(int sfd) //注册
{
//封装协议
climsg.type='1';
bzero(climsg.name,sizeof(climsg.name));
bzero(climsg.password,sizeof(climsg.password));
printf("请输入注册的用户名>>>\n");
fgets(climsg.name,sizeof(climsg.name),stdin);
climsg.name[strlen(climsg.name)-1]=0;
printf("请输入注册的密码>>>\n");
fgets(climsg.password,sizeof(climsg.password),stdin);
climsg.password[strlen(climsg.password)-1]=0;
//将数据包发送给服务器
if(send(sfd,&climsg,sizeof(climsg),0)<0)
{
ERR_MSG("send");
return -1;
}
//阻塞接收服务器的回复
if(recv(sfd,&climsg,sizeof(climsg),0)<0)
{
ERR_MSG("recv");
return -1;
}
if(climsg.type=='S')
{
fprintf(stderr,"注册成功,请登录\n");
}
else if(climsg.type=='E')
{
fprintf(stderr,"注册失败,请更换用户名\n");
}
return 0;
}
//创建套接字.链接客户端.绑定信息结构体
int net_ser()
{
//创建流式套接字
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("socket success\n");
//非必须绑定,连接服务器
//填充地址信息结构体
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)
{
ERR_MSG("connect");
return -1;
}
printf("connect success\n");
return sfd;
}
测试文件
#include "02_clifunc.h"
int main(int argc, const char *argv[])
{
//创建套接字.链接服务器.绑定信息结构体
int sfd=net_ser();
char choose=0;
char ct=0;
while(1)
{
START: system("clear");
pri_menu(); //主菜单界面
printf("请输入你的选项>>>\n");
choose=getchar();
while(getchar()!=10);
switch(choose)
{
case '1':
//注册
cli_register(sfd);
break;
case '2':
//登录
if(cli_login(sfd)>0)
{
while(1)
{
//进入查询菜单
system("clear");
sec_menu();
printf("请输入你的选项>>>\n");
ct=getchar();
while(getchar()!=10);
switch(ct)
{
case '4':
//查询单词
cli_find(sfd);
break;
case '5':
//历史记录查询
cli_history(sfd);
break;
case '6':
//退出登录
cli_quit(sfd);
goto START;
default:
fprintf(stdout,"输入有误,请重新输入\n");
break;
}
printf("输入任意字符清屏>>>\n");
while(getchar()!=10);
}
case '3':
//退出
goto END;
break;
default:
fprintf(stdout,"输入有误,请重新输入\n");
break;
}
}
printf("输入任意字符清屏>>>\n");
while(getchar()!=10);
}
END:
close(sfd); //关闭套接字
return 0;
}
实现效果
注册
登录
查询单词
查询历史记录
退出第查询界面,清空登录状态
退出第一层界面,客户端下线
重复登录