服务器
。h
#ifndef __DICT_H__
#define __DICT_H__
#include<stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include<sqlite3.h>
#include<stdlib.h>
#include <time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define PORT 2223
#define IP "192.168.31.32"
#define ERR_MSG(msg) do{\
fprintf(stderr,"line:%d",__LINE__);\
perror(msg);\
}while(0)
typedef struct cli_msg
{
char type; //L登录Z注册#退出查询C查询单词H查询历史记录Q注销删除历史记录
char name[20];//登录姓名
int password;//登录密码
char word[666];//需要查询的单词
int status;//登录状态
}Msg;
//历史记录包
typedef struct {
char type;//Y发送完N表示没发送完
char data[1000];//历史记录包
}His;
//变更用户状态值
int ChangeUserStatus(Msg rcvbuf,sqlite3*db,int status);
//遍历数据库
int*do_select(sqlite3*db);
//建立数据库表格存储个人历史记录
int StoreHistory(Msg rcvbuf,sqlite3*db,char*pres);
//创建身份密码表ID
int CreateLogin();
//创建历史记录表History
int CreateHistoryWord();
//单词导入数据库
int InsertWord_database();
//登录
int do_login(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
//注册
int do_SignIn(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
int do_LookUpWord(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
//查询单词历史记录
int do_LookUpHistory(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
//注销删除历史记录
int do_quit(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
//客户端普通退出
int do_exit(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
#endif
function。c
#include"dict.h"
//遍历数据库
int *do_select(sqlite3*db)
{
char sql[128]="select *from dict";
char**pres=NULL;
int row,column;
char*errmsg=NULL;
if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return NULL;
}
printf("row=%d,column=%d\n",row,column);
int *p=&column;
//释放查询的结果
sqlite3_free_table(pres);
return p;
}
//单词导入数据库
int InsertWord_database()
{
sqlite3*db=NULL;
if(sqlite3_open("./dict.db",&db)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_open fail %d|%s\n",\
__LINE__,sqlite3_errcode(db),sqlite3_errmsg(db));
return -1;
}
printf("open success\n");
//创建表格
char sql[128]="create table if not exists dict(word char,mean char);";
printf("sql=%s\n",sql);
char *errmsg=NULL;
if(SQLITE_OK!=sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
//判断数据库单词的行数如果已经插入则不需要重复插入
int *p=do_select(db);
printf("%d:%d\n",__LINE__,*p);
if(*p==0){
//打开文件
FILE*fd=fopen("./dict.txt","r");
if(fd==NULL){
perror("open");
return -1;
}
//插入数据库
char buf[128]="";
char sql1[128]="";
char arr[50]="";
//char *errmsg=NULL;
while(1){
bzero(buf,sizeof(buf));
bzero(arr,sizeof(arr));
if(fgets(buf,sizeof(buf),fd)==NULL){
printf("文件读取完毕\n");
return -1;
}
buf[strlen(buf)-1]='\0';
int i=0;
char*p=buf;
int j=0;
while(buf[i]!=' '){
p++;
arr[j++]=buf[i++];
}
while(buf[i]==' '&&buf[i+1]!=' '){
arr[j++]=' ';
i++;
while(buf[i]!=' '){
p++;
arr[j++]=buf[i++];
}
}
while(buf[i++]==' '){
p++;
}
sprintf(sql1,"%s (\"%s\",'%s')","insert into dict values",arr,p);
printf("sql1=%s\n",sql1);
if(SQLITE_OK!=sqlite3_exec(db,sql1,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
}
}
return 0;
}
//创建身份密码表
int CreateLogin()
{
sqlite3*db=NULL;
if(sqlite3_open("./dict.db",&db)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_open fail %d|%s\n",\
__LINE__,sqlite3_errcode(db),sqlite3_errmsg(db));
return -1;
}
printf("open success\n");
//1表示有用户登录0表示没有用户登录
char sql[128]="create table if not exists ID(name char,password int,status int);";
printf("sql=%s\n",sql);
char *errmsg=NULL;
if(SQLITE_OK!=sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
return 0;
}
//变更用户状态值0表示没有用户登录1表示有用户登录
int ChangeUserStatus(Msg rcvbuf,sqlite3*db,int status)
{
char sql1[128]="";
//设置登录状态0表示没有用户登录
sprintf(sql1,"%s%d %s'%s'","update ID set status=",status," where name=",rcvbuf.name);
char *errmsg=NULL;
printf("sql=%s\n",sql1);
if(SQLITE_OK!=sqlite3_exec(db,sql1,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
}
return -1;
}
//取出数据库的状态值
int getstatus(Msg rcvbuf,sqlite3*db, int *pstatus)
{
char**pres=NULL;
int row,column;
char*errmsg=NULL;
char sql[128]="";
sprintf(sql,"%s'%s'","select *from ID where name=",rcvbuf.name);
printf("%d:sql=%s\n",__LINE__,sql);
if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
int status=atoi(pres[5]);
printf("status = %d\n", status);
*pstatus = status;
return 0;
}
//登录Y表示登录成功N表示登录失败
int do_login(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db)
{
//判断登录名是否存在数据库中
char**pres=NULL;
int row,column;
char*errmsg=NULL;
char sql[128]="select *from ID";
if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
printf("row=%d,column=%d\n",row,column);
//判断登录名是否存在数据库中
int k;//k记录登录名在表中的位置
int i = 0;
for(i=0;i<(row+1)*column;i++){
if(i%column==0&&i!=0){
if(strcmp(rcvbuf.name,pres[i])==0){
k=i;
break;
}
}
}
//若遍历到结尾都没有找到相同的用户名,则发送N后退出
if(i == (row+1)*column)
{
printf("用户名不存在\n");
rcvbuf.type='N';
if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
ERR_MSG("send");
return -1;
}
return 0;
}
//用户名存在可以登录
rcvbuf.type='Y';
printf("%d:status=%d\n",__LINE__,rcvbuf.status);
//取出数据库的状态值
getstatus(rcvbuf,db, &(rcvbuf.status));
printf("%d:status=%d\n",__LINE__,rcvbuf.status);
if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
ERR_MSG("send");
return -1;
}
if(1 == rcvbuf.status)
{
printf("%s用户已经在线\n", rcvbuf.name);
return 0;
}
//接收密码信息
while(1){
rcvbuf.type='Y';
int res=recv(newfd,&rcvbuf,sizeof(rcvbuf),0);
if(res<0){
ERR_MSG("recv");
return -1;
}
//遍历密码信息
if(rcvbuf.password==atoi(pres[k+1])){
printf("登录成功\n");
//变更用户状态值为1;
ChangeUserStatus(rcvbuf,db,1);
rcvbuf.status=1;
rcvbuf.type='Y';
if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
ERR_MSG("send");
return -1;
}
break;
}
else{
printf("密码输入错误\n");
rcvbuf.type='N';
if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
ERR_MSG("send");
return -1;
}
printf("重新输入\n");
}
}
return 0;
}
//注册
int do_SignIn(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db)
{
//判断登录名是否存在数据库中
char**pres=NULL;
int row,column;
char*errmsg=NULL;
char sql[128]="select *from ID";
if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
printf("row=%d,column=%d\n",row,column);
//判断登录名是否存在数据库中
int flag=0;//0不存在1存在
for(int i=0;i<(row+1)*column;i++){
//只判断用户名那一列
if(i%column==0&&i!=0){
if(strcmp(rcvbuf.name,pres[i])==0){
flag=1;
break;
}
}
}
if(flag==1){
if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
ERR_MSG("send");
return -1;
}
printf("用户名存在\n");
}
else{
//可以注册
rcvbuf.type='Y';
if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
ERR_MSG("send");
return -1;
}
//插入信息进数据库
int res=recv(newfd,&rcvbuf,sizeof(rcvbuf),0);
if(res<0){
ERR_MSG("recv");
return -1;
}
char sql1[128]="";
int status=0;//设置登录状态0表示没有用户登录
sprintf(sql1,"%s ('%s',%d,%d)","insert into ID values",rcvbuf.name,rcvbuf.password,status);
char *errmsg=NULL;
printf("sql=%s\n",sql1);
if(SQLITE_OK!=sqlite3_exec(db,sql1,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
printf("send success\n");
}
puts("************\n");
return 0;
}
//查询单词
int do_LookUpWord(struct sockaddr_in cin,Msg rcvbuf,int sfd,sqlite3*db)
{
//遍历数据库单词判断是否存在该单词
printf("%d:%s\n",__LINE__,rcvbuf.name);
char**pres=NULL;
int row,column;
char*errmsg=NULL;
char sql[128]="select *from dict";
if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
printf("row=%d,column=%d\n",row,column);
//判断单词是否存在数据库中
int flag=0;//0不存在1存在
for(int i=0;i<(row+1)*column;i++){
//只判断单词那一列
if(i%column==0&&i!=0){
if(strcmp(rcvbuf.word,pres[i])==0){
//建立数据库表格存储历史记录
StoreHistory(rcvbuf,db,pres[i+1]);
rcvbuf.type='Y';
//发送意思和单词
sprintf(rcvbuf.word,"%s %s",rcvbuf.word,pres[i+1]);
if(send(sfd,&rcvbuf,sizeof(rcvbuf),0)<0){
ERR_MSG("send");
return -1;
}
flag=1;
}
}
}
//没有查到
if(flag==0){
rcvbuf.type='N';
if(send(sfd,&rcvbuf,sizeof(rcvbuf),0)<0){
ERR_MSG("send");
return -1;
}
}
return 0;
}
//建立数据库表格存储个人历史记录
int StoreHistory(Msg rcvbuf,sqlite3*db,char*pres)
{
char sql[128];
sprintf(sql,"%s %s (%s)","create table if not exists",rcvbuf.name,"word char,mean char,time char" );
printf("sql=%s\n",sql);
char *errmsg=NULL;
if(SQLITE_OK!=sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
//得到查询的时间
struct tm*info;
time_t t1=time(NULL);
info=localtime(&t1);
char time[120];
sprintf(time,"%d-%d-%d %d:%d:%d",info->tm_year+1900,info->tm_mon+1,info->tm_mday,info->tm_hour,info->tm_min,info->tm_sec);
//将历史记录插入数据库
char sql1[1000]="";
sprintf(sql1,"%s %s %s(\"%s\",'%s','%s')","insert into" ,rcvbuf.name, "values",rcvbuf.word,pres,time);
printf("%d:sql=%s\n",__LINE__,sql1);
if(SQLITE_OK!=sqlite3_exec(db,sql1,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
return 0;
}
//查询单词历史记录
int do_LookUpHistory(struct sockaddr_in cin,Msg rcvbuf,int sfd,sqlite3*db)
{
char sql[128];
char**pres=NULL;
int row,column;
char*errmsg=NULL;
sprintf(sql,"%s %s","select *from",rcvbuf.name);
printf("sql=%s\n",sql);
if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
printf("row=%d,column=%d\n",row,column);
//可能会出现沾包问题
His H_data;
H_data.type='N';
for(int i=3;i<(row+1)*column;i++){
bzero(&H_data,sizeof(H_data));
//拼接历史记录/Y发送完N表示没发送完
strcpy(H_data.data,pres[i]);
ssize_t res=send(sfd,&H_data,sizeof(H_data),0);
if(res<0){
ERR_MSG("send");
return -1;
}
}
H_data.type='Y';
if(send(sfd,&H_data,sizeof(H_data),0)<0){
ERR_MSG("send");
}
return 0;
}
//注销删除历史记录
int do_quit(struct sockaddr_in cin,Msg rcvbuf,int sfd,sqlite3*db)
{
//从登录表中删除个人信息
char sql[128]="";
sprintf(sql,"%s'%s'","delete from ID where name=",rcvbuf.name);
printf("sql=%s\n",sql);
char *errmsg=NULL;
if(SQLITE_OK!=sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
//删除个人的历史记录表
char sql1[128]="";
sprintf(sql1,"%s '%s'","drop table",rcvbuf.name);
printf("sql=%s\n",sql1);
if(SQLITE_OK!=sqlite3_exec(db,sql1,NULL,NULL,&errmsg)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_exec fail %s\n",\
__LINE__,errmsg);
return -1;
}
return 0;
}
//客户端普通退出
int do_exit(struct sockaddr_in cin,Msg rcvbuf,int sfd,sqlite3*db)
{
//变更用户状态值0表示没有用户登录1表示有用户登录
ChangeUserStatus(rcvbuf,db,0);
return -1;
}
main。c
#include"dict.h"
void task(int arg)
{
while(waitpid(-1,NULL,WNOHANG)>0);
}
int main(int argc, const char *argv[])
{
//回收僵尸进程
typedef void (*sighandler_t)(int);
sighandler_t s=signal(17, task);
//创建流套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0){
ERR_MSG("socket");
return -1;
}
printf("socket success __%d__\n",__LINE__);
//允许端口快速复用
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0){
ERR_MSG("setsockopt");
return -1;
}
//填充结构体
struct sockaddr_in sin;
sin.sin_family= AF_INET;
sin.sin_port=htons(PORT);
//IP网络字节序
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 __%d__\n",__LINE__);
//监听
if(listen(sfd,128)<0){
ERR_MSG("listen");
return -1;
}
printf("listen success __%d__\n",__LINE__);
//获取连接成功的文件描述符//NEWFD才是通信的描述符号//获取客户端的信息结构体
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
int newfd=-1;
//单词导入数据库
//遍历数据库,如果数据库行数小于不导入
printf("正在导入\n");
InsertWord_database();
printf("导入成功\n");
//创建身份密码表
printf("创建身份密码表\n");
CreateLogin();
printf("创建身份密码表成功\n");
//打开数据库
sqlite3*db=NULL;
if(sqlite3_open("./dict.db",&db)!=SQLITE_OK)
{
fprintf(stderr,"%d sqlite3_open fail %d|%s\n",\
__LINE__,sqlite3_errcode(db),sqlite3_errmsg(db));
return -1;
}
printf("open success\n");
//接收数据
while(1){
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_t pid=fork();
if(pid==0){
//关闭套接字
close(sfd);
//执行程序
Msg rcvbuf;
int res;
int status=0;//-1表示客户端正常退出,0表示ctrl+C退出
bzero(rcvbuf.name,sizeof(rcvbuf.name));
//L登录Z注册#退出查询C查询单词H查询历史记录Q注销删除历史记录
while(1)
{
//bzero(rcvbuf.name,sizeof(rcvbuf.name));
res=recv(newfd,&rcvbuf,sizeof(rcvbuf),0);
if(res<0){
ERR_MSG("recv");
return -1;
}
else if(res==0){
fprintf(stderr,"[%s : %d] newfd=%d,客户端下线\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
if(status==0){
//ctrl+c客户端下线删除历史记录和注销用户
//printf("注销客户端信息及删除个人历史记录\n");
printf("ctrl+c退出\n");
do_quit(cin,rcvbuf,newfd,db);//注销删除历史记录
}
break;
}
printf("[%s : %d] newfd=%d\nC:%s\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,rcvbuf.name);
switch(rcvbuf.type)
{
case 'L':
do_login(cin,rcvbuf,newfd,db);//登录
break;
case 'Z':
do_SignIn(cin,rcvbuf,newfd,db);//注册
break;
case 'C':
do_LookUpWord(cin,rcvbuf,newfd,db);//查询单词
break;
case 'H':
do_LookUpHistory(cin,rcvbuf,newfd,db);//查询单词历史记录
break;
case 'Q':
do_quit(cin,rcvbuf,newfd,db);//注销删除历史记录
break;
case 'X':
status=do_exit(cin,rcvbuf,newfd,db);//客户端普通退出
break;
default:
printf("协议 %c 错误 __%s__ __%d__\n", rcvbuf.type, __FILE__, __LINE__);
}
}
close(newfd);
exit(0);//退出子进程
}
else if(pid>0){
//多客户端连接
close(newfd);
}
else{
ERR_MSG("fork");
return 0;
}
}
//关闭数据库
if(sqlite3_close(db)!=SQLITE_OK){
fprintf(stderr,"%d sqlite3_close fail",__LINE__);
return -1;
}
close(sfd);
close(newfd);
return 0;
}
客户端
#include<stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include<stdlib.h>
#include <signal.h>
#include <sys/types.h>
#define PORT 2223
#define IP "192.168.31.32"
#define ERR_MSG(msg) do{\
fprintf(stderr,"line:%d",__LINE__);\
perror(msg);\
}while(0)
//登录信息结构体
typedef struct cli_msg
{
char type;//L登录Z注册#退出查询C查询单词H查询历史记录Q注销删除历史记录
char name[20];//登录名
int password;//登录密码
char word[666];
int status;//登录状态
}Msg;
//历史记录包
typedef struct {
char type;//Y发送完N表示没发送完
char data[1000];//历史记录包
}His;
//登录
Msg* do_login(int sfd)
{
Msg sndbuf;
char name[20]="";
int password;
int res;
Msg*p=(Msg*)malloc(sizeof(Msg));//堆区申请空间保存用户名
while(1){
while(1){
sndbuf.type='L';
printf("请输入登录名或#退出登录\n");
scanf("%s",name);
strcpy(sndbuf.name,name);
//退出到登录界面
if(strcmp(sndbuf.name,"#")==0){
strcpy(p->name,sndbuf.name);
return p;
}
if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
ERR_MSG("send");
return NULL;
}
res=recv(sfd,&sndbuf,sizeof(sndbuf),0);
if(res<0){
ERR_MSG("recv");
return NULL;
}
if(sndbuf.type=='Y'){
//0表示不在线1表示在线
printf("%d:%d\n",__LINE__,sndbuf.status);
if(sndbuf.status==0){
printf("请输入密码\n");
break;
}
else{
printf("用户在线\n");
}
}
printf("用户名不存在,请重新输入\n");
}
//sndbuf.type=Y表示登录成功
while(1){
int password;
scanf("%d",&password);
sndbuf.password=password;
if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
ERR_MSG("send");
return NULL;
}
res=recv(sfd,&sndbuf,sizeof(sndbuf),0);
if(res<0){
ERR_MSG("recv");
return NULL;
}
if(sndbuf.type=='Y'){
printf("登录成功\n");
strcpy(p->name,sndbuf.name);
return p;//返回登录名
}
printf("密码错误,请重新输入密码\n");
}
}
return NULL;
}
//注册
int do_SignIn(int sfd)
{
Msg sndbuf;
sndbuf.type='Z';
char name[20];
int password;
int res;
while(1){
while(1){
printf("请输入注册名\n");
scanf("%s",name);
strcpy(sndbuf.name,name);
if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
ERR_MSG("send");
return -1;
}
res=recv(sfd,&sndbuf,sizeof(sndbuf),0);
if(res<0){
ERR_MSG("recv");
return -1;
}
if(sndbuf.type=='Y'){
printf("请输入密码\n");
break;
}
printf("用户名已存在\n");
}
//sndbuf.type=Y表示注册成功
int password;
scanf("%d",&password);
sndbuf.password=password;
if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
ERR_MSG("send");
return -1;
}
printf("注册成功\n");
break;
}
return 0;
}
//查询单词
int do_LookUpWord(Msg*name,int sfd)
{
Msg sndbuf;
strcpy(sndbuf.name,name->name);
printf("%d:%s\n",__LINE__,sndbuf.name);
ssize_t res=-1;
while(1){
printf("请输入要查询的单词or # 退出查询\n");
bzero(sndbuf.word,sizeof(sndbuf.word));
scanf("%s",sndbuf.word);
sndbuf.type='C';
if(strcmp(sndbuf.word,"#")==0){
break;
}
if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
ERR_MSG("send");
return -1;
}
//接收服务器的信息
res=recv(sfd,&sndbuf,sizeof(sndbuf),0);
if(res<0){
ERR_MSG("recv");
return -1;
}
//判断是否查到单词Y表示查询到单词N表示没有查询到单词
if(sndbuf.type=='Y'){
printf("%s\n",sndbuf.word);
}
else{
printf("没有查询到这个单词\n");
}
}
return 0;
}
//查询单词历史记录
int do_LookUpHistory(Msg*name,int sfd)
{
Msg sndbuf;
His H_data;//历史记录包
strcpy(sndbuf.name,name->name);
sndbuf.type='H';
if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
ERR_MSG("send");
return -1;
}
//接收服务器的信息
int i=0;//调整格式
while(1){
//清空数据包Y发送完N表示没发送完
bzero(&H_data,sizeof(H_data));
ssize_t res=recv(sfd,&H_data,sizeof(H_data),0);
if(res<0){
ERR_MSG("recv");
return -1;
}
i++;
if(H_data.type=='Y'){
//最后一个包退出
puts("退出查询历史记录\n");
break;
}
printf("%s\t",H_data.data);
fflush(stdout);
if(i%3==0){
printf("\n");
}
}
return 0;
}
//注销用户删除历史记录表
int do_quit(Msg*name,int sfd)
{
Msg sndbuf;
sndbuf.type='Q';
strcpy(sndbuf.name,name->name);
if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
ERR_MSG("send");
return -1;
}
printf("删除成功\n");
//释放堆区空间
free(name);
name=NULL;
return 0;
}
int main(int argc, const char *argv[])
{
//创建流套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0){
ERR_MSG("socket");
return -1;
}
printf("socket success __%d__\n",__LINE__);
//允许端口快速复用(不写绑定)
//填充结构体
struct sockaddr_in sin;
sin.sin_family= AF_INET;
sin.sin_port=htons(PORT);
//IP网络字节序
sin.sin_addr.s_addr=inet_addr(IP);
if(-1==connect(sfd, (struct sockaddr*)&sin, sizeof(sin))){
ERR_MSG("connet");
return -1;
}
printf("connect serve success\n");
//登录操作
int choose;
Msg*name=NULL;
while(1){
BAGIN:
printf("**************************\n");
printf("**********1登录***********\n");
printf("**********2注册***********\n");
printf("**********3退出客户端*****\n");
printf("**************************\n");
printf("请输入>>>\n");
scanf("%d",&choose);
switch(choose){
case 1:
name=do_login(sfd);//登录信息
printf("%d:%s\n",__LINE__,name->name);
if(strcmp(name->name,"#")==0){
goto BAGIN;
}
break;
case 2:
do_SignIn(sfd);//注册
goto BAGIN;
case 3:
goto END;
default:
printf("输入错误,请重新输入\n");
goto BAGIN;
}
Msg sndbuf;
//查询操作
while(1){
printf("****************************\n");
printf("**********1查询单词*********\n");
printf("**********2查询历史记录*****\n");
printf("**********3注销用户*********\n");
printf("**********4退出用户重新登录*\n");
printf("**********5退出客户端*******\n");
printf("****************************\n");
printf("请输入>>>\n");
getchar();
scanf("%d",&choose);
switch(choose){
case 1:
do_LookUpWord(name,sfd);//查询单词
break;
case 2:
do_LookUpHistory(name,sfd);//查询单词历史记录
break;
case 3:
do_quit(name,sfd);//注销用户删除历史记录表
goto BAGIN;
case 4:
sndbuf.type='X';
strcpy(sndbuf.name,name->name);
printf("%d:%s\n",__LINE__,name->name);
if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
ERR_MSG("send");
return -1;
}
goto BAGIN;
case 5:
sndbuf.type='X';
strcpy(sndbuf.name,name->name);
if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
ERR_MSG("send");
return -1;
}
goto END;
default:
printf("输入错误__%d__\n", __LINE__);
}
}
}
END:
//释放堆区空间
free(name);
name=NULL;
//关闭套接字
close(sfd);
return 0;
}