1,在线词典功能,分为客户端和服务器端
2,客户端有三个模块:注册、登录、查询(查询单词、查询历史记录)
3,服务器端要实现多并发服务器,这里采用多进程并发服务器:注册、登录、查询(查询单词、查询历史记录)
4,用户分为普通用户和管理员用户:管理员用户可以查询所有普通用户的历史记录,还可以看到词库中未定义的单词查询记录,普通用户只能查到自己的,词库中中有定义的记录
5,客户端和服务器通信只要通过一个信息结构体实现:
typedef struct{
int flag; //1:usr or 2:root
int type;
char name[N];
char data[256]; //password or word
}MSG;
6,服务器端有单词词库
7,服务器端有两张数据库表格,一张用来存放用户信息,一张用来存放用户单词查询记录
8,多进程并发服务器要做僵尸进程处理
2,框架图
2.1,客户端框架
2.1,服务器端框架
3,代码
3.1,客户端代码
#include#include#include#include#include#include#include#include#include#define N 20#define R 1#define L 2#define Q 3#define H 4#define USR 1#define ROOT 2typedefstruct{int flag;//1:usr or 2:rootint type;char name[N];char data[256];//password or word}MSG;intdo_client(int sockfd);intdo_register(int connectfd,MSG *msg);intdo_login(int connectfd,MSG *msg);intdo_query(int connectfd,MSG *msg);intdo_history(int connectfd,MSG *msg);intmain(int argc,constchar*argv[]){int serverfd;struct sockaddr_in sin;if(argc !=3){printf("usage: %s
",argv[0]);exit(0);}//创建流式套接字if((serverfd =socket(AF_INET,SOCK_STREAM,0))<0){perror("socket");exit(-1);}//填充协议地址结构体bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port =htons(atoi(argv[2]));
sin.sin_addr.s_addr =inet_addr(argv[1]);//连接服务器if(connect(serverfd,(struct sockaddr *)&sin,sizeof(sin))<0){perror("connect");goto _error1;}do_client(serverfd);
_error1:close(serverfd);return0;}intdo_client(int sockfd){
MSG msg;bzero(&msg,sizeof(msg));
msg.flag =-1;while(msg.flag <0){printf("Please choose permission [1:usr 2:root]");if(scanf("%d",&msg.flag)==0)
msg.flag =-1;while(getchar()!='
');if(msg.flag !=1&& msg.flag !=2)
msg.flag =-1;}/* 注册登录模块 */while(1){
msg.type =-1;while(msg.type <0){printf("********************************************
");printf("*1:register 2:login 3:quite *
");printf("********************************************
");printf("PLease choose:");if(scanf("%d",&msg.type)==0)
msg.type =-1;while(getchar()!='
');}switch(msg.type){case R:{do_register(sockfd,&msg);break;}case L:{if(do_login(sockfd,&msg)==1){goto _NEXT;}break;}case3:{close(sockfd);printf("Exit the online dictionary program
");exit(0);break;}default:printf("Error cmd.
");}}
_NEXT:/* 查询模块 */while(1){
msg.type =-1;while(msg.type <0){printf("********************************************
");printf("*1:query_word 2:history_record 3:quite *
");printf("********************************************
");printf("Please choose:");if(scanf("%d",&msg.type)==0)
msg.type =-1;while(getchar()!='
');}switch(msg.type){case1:{
msg.type = Q;do_query(sockfd,&msg);break;}case2:{
msg.type = H;do_history(sockfd,&msg);break;}case3:{close(sockfd);printf("Exit the online dictionary program
");exit(0);break;}default:printf("Error cmd.
");}}}intdo_register(int connectfd,MSG *msg){char str[20];int flag;while(1){printf("PLease input name:");if(scanf("%s",msg->name)){};while(getchar()!='
');
flag =-1;while(flag <0){printf("PLease input password:");if(scanf("%s",str)){};while(getchar()!='
');printf("Please confirm password:");if(scanf("%s",msg->data)){};while(getchar()!='
');if(strncmp(msg->data,str,strlen(str))==0){
flag =1;}else{printf("Entered passwords differ,Please re-enter them.
");}}if(send(connectfd,msg,sizeof(MSG),0)<0){perror("do_register fail to send");return-1;}if(recv(connectfd,msg,sizeof(MSG),0)<0){perror("do_register fail to recv");return-1;}if(strncasecmp(msg->data,"ok",strlen("ok"))==0){printf("register success.
");return1;break;}else{printf("%s
",msg->data);printf("re-register or cancel [1:re-register 2:cancel]");int tmp;if(scanf("%d",&tmp)){};while(getchar()!='
');if(tmp ==2)break;}}return0;}intdo_login(int connectfd,MSG *msg){while(1){printf("PLease input name:");if(scanf("%s",msg->name)){};while(getchar()!='
');printf("PLease input password:");if(scanf("%s",msg->data)){};while(getchar()!='
');if(send(connectfd,msg,sizeof(MSG),0)<0){perror("do_login fail to send");return-1;}if(recv(connectfd,msg,sizeof(MSG),0)<0){perror("do_login fail to recv");return-1;}if(strncasecmp(msg->data,"ok",strlen("ok"))==0){printf("login success.
");return1;break;}else{printf("%s
",msg->data);printf("re-login or cancel [1:re-login 2:cancel]");int tmp;if(scanf("%d",&tmp)){};while(getchar()!='
');if(tmp ==2)break;}}return0;}intdo_query(int connectfd,MSG *msg){while(1){printf("Please input query_word('#' exit):");if(scanf("%s",msg->data)){};while(getchar()!='
');/* 返回上级菜单 */if(strncmp(msg->data,"#",strlen("#"))==0){break;}/* 把含有有查询单词的消息结构体发送给服务器 */if(send(connectfd,msg,sizeof(MSG),0)<0){perror("do_query fail to send.");return-1;}/* 阻塞接受 */if(recv(connectfd,msg,sizeof(MSG),0)<0){perror("do_query fail to recv.");return-1;}/* 处理从服务器接受的信息 */printf("%s",msg->data);}return0;}intdo_history(int connectfd,MSG *msg){if(send(connectfd,msg,sizeof(MSG),0)<0){perror("do_history fail to send");return-1;}while(1){if(recv(connectfd,msg,sizeof(MSG),0)<0){perror("do_history fail to recv");return-1;}#if 1if(msg->data[0]=='