9.16总结
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <myhead.h>#define SER_PORT 8888
#define SER_IP "192.168.71.128"//处理僵尸进程
void handler(int signo)
{if(SIGCHLD == signo){while(waitpid(-1,NULL,WNOHANG)>0);}
}//注册模块
int add_login(sqlite3 *ppDb,char *name,int password)
{char sql[128]="";sprintf(sql,"insert into user values(\"%s\",%d)",name,password);char *errmsg =NULL;if(sqlite3_exec(ppDb,sql,NULL,NULL,&errmsg)!=SQLITE_OK){printf("注册失败 %s\n",errmsg);sqlite3_free(errmsg);errmsg = NULL;return -1;}if(sqlite3_changes(ppDb)>0){printf("注册成功\n");return 0;}return -1;
}//验证登录信息的模块
int callback(void *arg,int cols,char **msgtext,char **msgheader)
{int *flag_t = (int *)arg;*flag_t = 1;return 0;
}//登录模块
int add_enter(sqlite3 *ppDb,char *name,int password)
{char sql[128]="";sprintf(sql,"select * from user where name = '%s' and password = %d",name,password);int flag = -1;char *errmsg =NULL;if(sqlite3_exec(ppDb,sql,callback,&flag,&errmsg)!=SQLITE_OK){printf("登录失败 %s\n",errmsg);sqlite3_free(errmsg);errmsg=NULL;return -1;}if(flag == 1){printf("登录成功\n");return 0;}else{printf("登录失败,账号或者密码错误请重新尝试\n");return -1;}
}int add_dict(sqlite3 *ppDb)
{FILE *fp=fopen("dict.txt","r");if(fp == NULL){perror("open error");return -1;}char line[1024]="";char *word,*chinese;int count = 0;char *errmsg = NULL;while(fgets(line,sizeof(line),fp)!=NULL){line[strcspn(line,"\n")]='\0'; //这个函数的作用是遍历这个数组直到找到参数2的字符,然后返回已经遍历的个数word = strtok(line," ");chinese = strtok(NULL,"\0");if(word!=NULL&&chinese!=NULL){char sql[1024] = "";sprintf(sql,"insert into dictionaries values('%s','%s')",word,chinese);if(sqlite3_exec(ppDb,sql,NULL,NULL,&errmsg)!=SQLITE_OK){printf("字典建立失败 :%s\n",errmsg);sqlite3_free(errmsg);errmsg=NULL;}if(sqlite3_changes(ppDb)>0){printf("字典建立成功\n");}}fclose(fp);return 0;}
}
/*--------------主程序-----------*/
int main(int argc, const char *argv[])
{if(signal(SIGCHLD,handler)==SIG_ERR){perror("signal error");return -1;}int sfd = socket(AF_INET,SOCK_STREAM,0);if(sfd == -1){perror("socket error");return -1;}struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(SER_PORT);sin.sin_addr.s_addr = inet_addr(SER_IP);if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))== -1){perror("bind error");return -1;}if(listen(sfd,128) == -1){perror("listen error");return -1;}int reuse = 1;if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){perror("setsockopt error");return -1;}struct sockaddr_in cin;socklen_t addrlen = sizeof(cin);sqlite3 *ppDb = NULL;if(sqlite3_open("./user.db",&ppDb)!=SQLITE_OK){printf("open error");return -1;}//用户表char *sql = "create table if not exists user(name char primary key,password int);";char *errmsg = NULL;if(sqlite3_exec(ppDb,sql,NULL,NULL,&errmsg)!=SQLITE_OK){printf("用户表创建失败 %s\n",errmsg);sqlite3_free(errmsg);errmsg =NULL;return -1;}//电子词典char *sqk = "create table if not exists dictionaries(word char,chinese char);";char *errmsg_t = NULL;if(sqlite3_exec(ppDb,sqk,NULL,NULL,&errmsg_t)!= SQLITE_OK){printf("电子词典建立失败 %s\n",errmsg_t);sqlite3_free(errmsg_t);errmsg_t = NULL;return -1;}add_dict(ppDb);while(1){int newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);if(newfd == -1){perror("acceot error");continue;}printf("[%s:%d]链接成功new=%d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);pid_t pid = fork();if(pid>0){close(newfd);}if(pid == 0){close(sfd);char buf[512]="";while(1){int len = recv(newfd,buf,sizeof(buf)-1,0);if(len == 0){printf("客户端断开连接\n");break;}buf[len] = '\0';printf("来自客户端的消息:%s\n",buf);char order[20],name[20],password_t[20];char reply[128]="";//这里主要使用strtok函数来分割客户端传来的字符串//分割完成后再依次判断,根据传入order的字符串判断是什么请求char *token = strtok(buf," ");if(token!=NULL){strcpy(order,token);token=strtok(NULL, " ");}else{strcpy(reply,"缺少命令");send(newfd,reply,strlen(reply),0);continue;}if(token!=NULL){strcpy(name,token);token = strtok(NULL," ");}else{strcpy(reply,"缺少账号");send(newfd,reply,strlen(reply),0);continue;}if(token!=NULL){strcpy(password_t,token);token=strtok(NULL," ");}else{strcpy(reply,"缺少密码");send(newfd,reply,strlen(reply),0);continue;}int password = atoi(password_t);if(strcmp(order,"zhuce")==0){if(add_login(ppDb,name,password)==0){strcpy(reply,"注册成功");}else{strcpy(reply,"注册失败");}}else if(strcmp(order,"denglu")==0){if(add_enter(ppDb,name,password)==0){strcpy(reply,"登录成功");}else{strcpy(reply,"登录失败");}}else if(strcmp(order,"quit")==0){strcpy(reply,"退出成功");send(newfd,reply,strlen(reply),0);break;}send(newfd,reply,strlen(reply),0);close(newfd);exit(0);}}}sqlite3_close(ppDb);close(sfd);return 0;
}
上面是服务器代码,下面是客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <myhead.h>#define SER_PORT 8888
#define SER_IP "192.168.71.128"void do_lgin(int sfd)
{printf("============功能选择==========\n");printf("=============1.查阅===========\n");printf("=========2.查看历史记录=======\n");printf("==========3.返回上一级========\n");printf("请选择功能:");int pos =-1;scanf(" %d",&pos);getchar();switch(pos){case 1:printf("请输入需要查阅的单词:");char buf[128]="";fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]=0;char query[258]="";sprintf(query,"query,%s",buf);send(sfd,query,sizeof(query),0);char rbuf[512]="";int len = recv(sfd,rbuf,strlen(rbuf),0);if(len>0){rbuf[len]='\0';printf("查阅结果为: %s\n",rbuf);}break;case 2:break;case 0:exit(0);}
}int main(int argc, const char *argv[])
{int sfd = socket(AF_INET,SOCK_STREAM,0);if(sfd == -1){perror("socket error");return -1;}struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(SER_PORT);sin.sin_addr.s_addr = inet_addr(SER_IP);if(connect(sfd,(struct sockaddr*)&sin,sizeof(sin))== -1){perror("connect error");return -1;}char buf[128]= "";int pos =-1;char name[20]="";char password[20]="";;char receive[512]="";while(1){printf("============登录界面================\n");printf("=============1.注册===================\n");printf("=============2.登录===================\n");printf("=============0.退出===================\n");printf("请选择功能:");scanf(" %d",&pos);getchar();switch(pos){//下面依次为注册,登录,退出模块case 1:printf("请输入注册信息\n");printf("请输入注册账号:");fgets(name,sizeof(name),stdin);name[strlen(name)-1] = 0;printf("请输入注册密码:");fgets(password,sizeof(password),stdin);password[strlen(password)-1] = 0;sprintf(buf,"zhuce %s %s",name,password);send(sfd,buf,strlen(buf),0);int len_1 = recv(sfd,receive,sizeof(receive),0);if(len_1>0){receive[len_1] = '\0';printf("服务器答复:%s\n",receive);}break;case 2:printf("请输入登录信息\n");printf("请输入登录账号:");fgets(name,sizeof(name),stdin);name[strlen(name)-1] = 0;printf("请输入登录密码:");fgets(password,sizeof(password),stdin);password[strlen(password)-1] = 0;sprintf(buf,"denglu %s %s",name,password);send(sfd,buf,strlen(buf),0);int len_2 = recv(sfd,receive,sizeof(receive),0);if(len_2>0){receive[len_2] = '\0';printf("服务器答复:%s\n",receive);}do_lgin(sfd);break;case 0:send(sfd,"quit", 4 ,0);int len_3 = recv(sfd,receive,sizeof(receive),0);if(len_3>0){receive[len_3] = '\0';printf("服务器答复:%s\n",receive);}close(sfd);return 0;default:printf("输入错误,请重新输入\n");}} close(sfd);return 0;
}
还有字典的查询和历史记录未实现