第一题:提交在线词典项目功能实现相关代码(将源代码打包后上传)
1、在搭建的框架中实现并发,实现多客户端的注册登录
2、同时支持管理员(用户名:root,密码:1)和普通用户,提示:可以在通信的结构体中添加flag标志位判断是root用户还是普通用户
3、管理员可以查询所有用户的使用记录(将源代码打包后上传)
(作业要求:做作业的时候不要再翻看视频上的教程,对函数理解不明白的全部通过man手册去查看,
自己思考框架,使用makefile编译,然后将测试的记录和结果添加到readme.txt文件中提交上来,代码实现完成测试通过后
再提交作业,网络部分学习不写代码不测试看不出问题的,良好的习惯帮助你们快速成长。)
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <signal.h> #include <sqlite3.h> #include <errno.h> #include <time.h> #define SERV_PORT 5050 #define SERV_IP_ADDR "192.168.1.158" #define FILEADDR "MyDictionary.db" #define TABLE_USR "usr" #define TABLE_RECORD "record" #define SZ_DICT 512 #define R 1 #define L 2 #define Q 3 //Query_Word #define H 4 //History_Record #define U 5 //USR LIST #define DONE -1 #define N 32 /* * 2020-10-08 by ku-yufeng * 在线辞典的服务端框架 * * * */ typedef struct { int type; char name[N]; char data[256]; //password or word } MSG; void do_register(int fd,MSG* msg,sqlite3* db); int do_login(int fd, MSG* msg,sqlite3* db); int do_query(int fd, MSG* msg,sqlite3* db); int do_history(int fd, MSG* msg,sqlite3* db); int sqlcallback(void *para, int f_num, char **f_value, char **f_name); int do_searchword(char* word); char* get_date(); int do_regRoot(sqlite3* db); int do_userlist(int fd,MSG* msg,sqlite3* db); int FLAG; char NAME[N]; int SUPER_USR; int main(int argc, const char *argv[]) { int fd,newfd; sqlite3* db; int result; ssize_t ret; MSG msg; pid_t pid; bzero((void*)&msg,sizeof(MSG)); struct sockaddr_in mysockaddr; result = sqlite3_open(FILEADDR,&db); if(result != SQLITE_OK) { printf("%s\n",sqlite3_errmsg(db)); return -1; } ret = do_regRoot(db); //创建 root 管理员账号 密码为1 if(ret!=0) return -1; fd = socket(AF_INET,SOCK_STREAM,0); if(fd == -1) { perror("SOCKET"); return -1; } bzero((void*)&mysockaddr,sizeof(struct sockaddr_in)); mysockaddr.sin_family = AF_INET; mysockaddr.sin_port = htons(SERV_PORT); //网络字节序的端口号 result = inet_pton(AF_INET,SERV_IP_ADDR,(void*)&mysockaddr.sin_addr); //网络字节序的IP地址 if(result != 1) { perror("inet_pton"); return -1; } result = bind(fd,(struct sockaddr *)&mysockaddr,sizeof(struct sockaddr_in)); printf("Server staring...OK!\n"); if(result != 0) { perror("bind"); close(fd); return -1; } signal(SIGCHLD,SIG_IGN); //不在意返回值,交由系统自动回收。防止产生僵尸进程。 result = listen(fd,5); if(result!=0) { perror("listen"); return -1; } LOOP1: newfd = accept(fd,NULL,NULL); if(newfd <0 ){ perror("accept"); return -1; } pid = fork(); if(pid < 0) { perror("fork"); return -1; } else if(0 == pid) //子进程 { while(1) { do{ ret = recv(newfd,(void*)&msg,sizeof(msg),0); }while(ret<0 && EINTR ==errno); if(ret<0) { perror("recv"); return -1; } else if(!ret) { break; } printf("type: %d\n",msg.type); switch(msg.type) { case R: do_register(newfd, &msg,db); break; case L: do_login(newfd, &msg,db); break; case Q: do_query(newfd,&msg,db); break; case H: do_history(newfd,&msg,db); break; case U: do_userlist(newfd,&msg,db); break; default:printf("Invalid data msg\n"); } } printf("client exit.\n"); close(newfd); } else //父进程 { goto LOOP1; } return 0; } void do_register(int fd,MSG* msg,sqlite3* db) { char sql[500] = {0}; char* errmsg; int result; sprintf(sql,"insert into %s values('%s','%s');",TABLE_USR,msg->name,msg->data); result = sqlite3_exec(db,sql,NULL,NULL,&errmsg); if(result != SQLITE_OK) { printf("%s\n",sqlite3_errmsg(db)); bzero((void*)msg,sizeof(MSG)); strcpy(msg->data,"already exist"); result = send(fd,msg,sizeof(MSG),0); return; } bzero((void*)msg,sizeof(MSG)); strcpy(msg->data,"OK!"); result = send(fd,msg,sizeof(MSG),0); printf("Register success!\n"); return; } int do_login(int fd, MSG* msg,sqlite3* db) { char sql[500] = {0}; char* errmsg; int result; sprintf(sql,"select * from '%s' where name = '%s' and password = '%s';",TABLE_USR,msg->name,msg->data); printf("%s\n",sql); FLAG =0; result = sqlite3_exec(db,sql,sqlcallback,NULL,&errmsg); if(result != SQLITE_OK || FLAG==0) { printf("%s\n",sqlite3_errmsg(db)); bzero((void*)msg,sizeof(MSG)); strcpy(msg->data,"usr/pwd wrony"); result = send(fd,msg,sizeof(MSG),0); return -1; } strcpy(NAME,msg->name); if(!strcmp(NAME,"root")) SUPER_USR = 0; //管理员为0 普通用户为1 else SUPER_USR = 1; bzero((void*)msg,sizeof(MSG)); strcpy(msg->data,"OK!"); result = send(fd,msg,sizeof(MSG),0); printf("Login success!\n"); return 0; } int do_query(int fd, MSG* msg,sqlite3* db) { int ret; char sql[500] = {0}; char* errmsg; char* localtime; char word[256]; strcpy(word,msg->data); ret = do_searchword(msg->data); printf("ret = %d, string = %s\n",ret,msg->data); if(ret == 1) { //返回查询到的数据到客户端 ret = send(fd,msg,sizeof(MSG),0); printf("Success for search!\n"); //存储查询记录 localtime = get_date(); localtime[strlen(localtime)-1] = 0; sprintf(sql,"insert into %s values('%s','%s','%s');",TABLE_RECORD,NAME,localtime,word); printf("%s\n",sql); ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg); if(ret != SQLITE_OK) { printf("%s\n",sqlite3_errmsg(db)); return -1; } } else { bzero((void*)msg,sizeof(MSG)); strcpy(msg->data,"not found!\n"); ret = send(fd,msg,sizeof(MSG),0); printf("fail for search!\n"); } return 0; } int do_history(int newfd, MSG* msg,sqlite3* db) { char sql[500] = {0}; char box[3][128] = {0}; char* errmsg; char** pazResult; int nrow,ncolumn,sqlerr; int i,j,index; if(0 == SUPER_USR) { sprintf(sql,"select * from %s where name = '%s';",TABLE_RECORD,msg->name); } else if(1 == SUPER_USR) { sprintf(sql,"select * from %s where name = '%s';",TABLE_RECORD,NAME); } printf("sql:%s\n",sql); sqlerr = sqlite3_get_table(db,sql,&pazResult,&nrow,&ncolumn,&errmsg); if(sqlerr != SQLITE_OK){ printf("%s\n",sqlite3_errmsg(db)); return -1; } else{ printf("Success for HISTORY\n"); for(i=0,index=0;i<=nrow;i++){ bzero((void*)box[0],128*3); for(j=0;j<ncolumn;j++,index++){ sprintf(box[j],"%-32s",pazResult[index]); printf("%s",box[j]); } bzero((void*)msg,sizeof(MSG)); sprintf(msg->data,"%s%s%s",box[0],box[1],box[2]); send(newfd,msg,sizeof(MSG),0); printf("\n"); } bzero((void*)msg,sizeof(MSG)); msg->type = DONE; send(newfd,msg,sizeof(MSG),0); } return 0; } int sqlcallback(void *para, int f_num, char **f_value, char **f_name) { FLAG = 1; printf("f_num = %d\n",f_num); if(f_num <= 0) { return -1; } return 0; } int do_searchword(char* word) { printf("进入serchword\n"); FILE* fp; char botton[SZ_DICT]; int ret; if((fp = fopen("dict.txt","r"))==NULL){ printf("字典打开失败!\n"); return 0; } while(fgets(botton,SZ_DICT,fp)!=NULL) { ret = strncmp(botton,word,strlen(word)); if(ret < 0 ) { bzero(botton,sizeof(botton)); continue; } if(ret > 0 && botton[0]>='a' && botton[0]<'z') { //printf("无数据1\n"); fclose(fp); return 0; } if(ret==0 && botton[strlen(word)] != ' ') { //printf("无数据2\n"); fclose(fp); return 0; } if(ret==0) { //printf("%s\n",botton); bzero((void*)word,strlen(word)); strncpy(word,botton,256); break; } } fclose(fp); return 1; } char* get_date() { time_t timep; time(&timep); printf("%s",asctime(gmtime(&timep))); return asctime(gmtime(&timep)); } int do_regRoot(sqlite3* db) { char sql[500] = {0}; char* errmsg; int result; sprintf(sql,"select * from '%s' where name = 'root' and password = '1';",TABLE_USR); printf("%s\n",sql); FLAG =0; result = sqlite3_exec(db,sql,sqlcallback,NULL,&errmsg); if(result != SQLITE_OK) { printf("%s\n",sqlite3_errmsg(db)); return -1; } if((FLAG == 0) && (SQLITE_OK == result)) { sprintf(sql,"insert into %s values('root','1');",TABLE_USR); result = sqlite3_exec(db,sql,sqlcallback,NULL,&errmsg); if(result != SQLITE_OK) { printf("%s\n",sqlite3_errmsg(db)); return -1; } } return 0; } int do_userlist(int fd,MSG* msg,sqlite3* db) { char sql[500] = {0}; char box[2][N] = {0}; char* errmsg; char** pazResult; int nrow,ncolumn,sqlerr; int i,j,index; printf("进入do_userlist!\n"); sprintf(sql,"select * from %s;",TABLE_USR); sqlerr = sqlite3_get_table(db,sql,&pazResult,&nrow,&ncolumn,&errmsg); if(sqlerr != SQLITE_OK){ printf("%s\n",sqlite3_errmsg(db)); return -1; } else{ printf("Success for HISTORY\n"); for(i=0,index=0;i<=nrow;i++){ bzero((void*)box[0],N*2); for(j=0;j<ncolumn;j++,index++){ // printf("%-31s",pazResult[index]); sprintf(box[j],"%-31s",pazResult[index]); printf("%s",box[j]); } bzero((void*)msg,sizeof(MSG)); sprintf(msg->data,"%s%s",box[0],box[1]); send(fd,msg,sizeof(MSG),0); printf("\n"); } bzero((void*)msg,sizeof(MSG)); msg->type = DONE; send(fd,msg,sizeof(MSG),0); } return 0 ; }
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <errno.h> #define SERV_PORT 5050 #define SERV_IP_ADDR "192.168.1.158" #define R 1 //Register #define L 2 //Login #define Q 3 //Query_Word #define H 4 //History_Record #define U 5 //Usr List #define DONE -1 #define N 32 /* * 2020-10-08 by ku-yufeng * 在线辞典的客户端框架 * * * */ typedef struct { int type; char name[N]; char data[256]; //password or word } MSG; void do_register(int fd,MSG* msg); int do_login(int fd, MSG* msg); int do_query(int fd, MSG* msg); int do_history(int fd, MSG* msg); int do_history_r(int fd, MSG* msg); int main(int argc, const char *argv[]) { int fd; int result,cmd; MSG msg; bzero((void*)&msg,sizeof(MSG)); struct sockaddr_in mysockaddr; fd = socket(AF_INET,SOCK_STREAM,0); if(fd == -1) { perror("SOCKET"); return -1; } bzero((void*)&mysockaddr,sizeof(struct sockaddr_in)); mysockaddr.sin_family = AF_INET; mysockaddr.sin_port = htons(SERV_PORT); //网络字节序的端口号 result = inet_pton(AF_INET,SERV_IP_ADDR,(void*)&mysockaddr.sin_addr); //网络字节序的IP地址 if(result != 1) { perror("inet_pton"); return -1; } printf("Client staring...OK!\n"); result = connect(fd,(struct sockaddr *)&mysockaddr,sizeof(struct sockaddr_in)); if(result != 0) { perror("connect"); close(fd); return -1; } while(1) { printf("**************************************************\n"); printf("* 1:Register 2:Login 3.Quit *\n"); printf("**************************************************\n"); printf("please choose: "); scanf("%d",&cmd); setbuf(stdin,NULL); switch(cmd) { case 1: do_register(fd,&msg); break; case 2: result = do_login(fd,&msg); if(result == 1) { goto next; //普通用户登陆的导航界面 } if(result == 2) { goto next_r; //root用户登陆的导航界面 } break; case 3: close(fd); exit(0); break; default:printf("CMD is illegal!\n"); } } next: while(1) { printf("**************************************************\n"); printf("* 1:Query_Word 2:History_Record 3.Quit *\n"); printf("**************************************************\n"); printf("please choose: "); scanf("%d",&cmd); switch(cmd) { case 1: do_query(fd,&msg); break; case 2: do_history(fd,&msg); break; case 3: close(fd); exit(0); default:printf("please select 1~3\n");cmd =0; } setbuf(stdin,NULL); } next_r: while(1) { printf("**************************************************\n"); printf("* WELCOME BACK MR.ROOT! *\n"); printf("* 1:Query_Word 2:History_Record 3.Quit *\n"); printf("**************************************************\n"); printf("please choose: "); scanf("%d",&cmd); switch(cmd) { case 1: do_query(fd,&msg); break; case 2: do_history_r(fd,&msg); break; case 3: close(fd); exit(0); default:printf("please select 1~3\n");cmd =0; } setbuf(stdin,NULL); } return 0; } void do_register(int fd,MSG* msg) { ssize_t ret; bzero((void*)msg,sizeof(MSG)); printf("Set name please:"); scanf("%s",msg->name); fflush(stdin); printf("Set password please:"); scanf("%s",msg->data); fflush(stdin); msg->type = R; ret = send(fd,msg,sizeof(MSG),0); if(ret<0) { perror("send"); return; } bzero(msg,sizeof(MSG)); do{ ret = recv(fd,msg,sizeof(MSG),0); }while(ret<0 && EINTR == errno); if(ret<0) { perror("recv"); return; } else if(!ret) { printf("server exit.\n"); exit(0); } ret = strcmp(msg->data,"OK!"); if(!ret){ printf("Register Success!\n"); } else if(!strcmp(msg->data,"already exist")){ printf("Register fail,name is exist!\n"); } else{ printf("不明错误原因,请与管理员联系\n"); } return; } int do_login(int fd, MSG* msg) { ssize_t ret; char name[N]={0}; bzero((void*)msg,sizeof(MSG)); printf("User name: "); scanf("%s",msg->name); setbuf(stdin,NULL); strcpy(name,msg->name); printf("PIN : "); scanf("%s",msg->data); setbuf(stdin,NULL); msg->type = L; ret = send(fd,msg,sizeof(MSG),0); if(ret<0) { perror("send"); return 0; } bzero(msg,sizeof(MSG)); do{ ret = recv(fd,msg,sizeof(MSG),0); }while(ret<0 && EINTR == errno); if(ret<0) { perror("recv"); return 0; } else if(!ret) { printf("server exit.\n"); exit(0); } ret = strcmp(msg->data,"OK!"); if(!ret){ printf("Login Success!\n"); if(!strcmp(name,"root")) return 2; return 1; } else{ printf("USER/PIN Wrony!\n"); } return 0; } int do_query(int fd, MSG* msg) { ssize_t ret; bzero((void*)msg,sizeof(MSG)); while(1) { printf("Set down a word,which you want to search('#' to quit...): "); scanf("%s",msg->data); setbuf(stdin,NULL); msg->type = Q; if(!strncmp(msg->data,"#",1)) { printf("查询完毕...\n"); return 0; } ret = send(fd,msg,sizeof(MSG),0); if(ret<0) { perror("send"); return 0; } bzero(msg,sizeof(MSG)); do{ ret = recv(fd,msg,sizeof(MSG),0); }while(ret<0 && EINTR == errno); if(ret<0) { perror("recv"); return 0; } else if(!ret) { printf("server exit.\n"); exit(0); } printf("----------------------------------------------\n"); printf("%s",msg->data); printf("----------------------------------------------\n"); } printf("query word success!\n"); return 0; } int do_history(int fd, MSG* msg) { ssize_t ret; bzero((void*)msg,sizeof(MSG)); msg->type = H; ret = send(fd,msg,sizeof(MSG),0); if(ret<0) { perror("send"); return 0; } while(1) { bzero(msg,sizeof(MSG)); do{ ret = recv(fd,msg,sizeof(MSG),0); }while(ret<0 && EINTR == errno); if(ret<0) { perror("recv"); return 0; } else if(!ret) { printf("server exit.\n"); exit(0); } if(msg->type == DONE) break; printf("%s\n",msg->data); } return 0; } int do_history_r(int fd, MSG* msg) { /* 打印用户名 供用户选择要查询记录的用户 */ ssize_t ret; bzero((void*)msg,sizeof(MSG)); msg->type = U; ret = send(fd,msg,sizeof(MSG),0); if(ret<0) { perror("send"); return 0; } while(1) { bzero(msg,sizeof(MSG)); do{ ret = recv(fd,msg,sizeof(MSG),0); }while(ret<0 && EINTR == errno); if(ret<0) { perror("recv"); return 0; } else if(!ret) { printf("server exit.\n"); exit(0); } if(msg->type == DONE) break; printf("%s\n",msg->data); } /* 根据管理员选择的用户名 进行查询 */ bzero((void*)msg,sizeof(MSG)); msg->type = H; printf("Witch one do you want to search?\n"); scanf("%s",msg->name); ret = send(fd,msg,sizeof(MSG),0); if(ret<0) { perror("send"); return 0; } while(1) { bzero(msg,sizeof(MSG)); do{ ret = recv(fd,msg,sizeof(MSG),0); }while(ret<0 && EINTR == errno); if(ret<0) { perror("recv"); return 0; } else if(!ret) { printf("server exit.\n"); exit(0); } if(msg->type == DONE) break; printf("%s\n",msg->data); } return 0; }
linux@ubuntu:~/Level8/day3$ ./client Client staring...OK! ************************************************** * 1:Register 2:Login 3.Quit * ************************************************** please choose: 1 Set name please:dashuaibi Set password please:123 Register Success! ************************************************** * 1:Register 2:Login 3.Quit * ************************************************** please choose: 2 User name: dashuaibi PIN : 123 Login Success! ************************************************** * 1:Query_Word 2:History_Record 3.Quit * ************************************************** please choose: 1 Set down a word,which you want to search('#' to quit...): dog ---------------------------------------------- dog n. common domestic animal kept by human beings for work, hunting, etc or as a pet ---------------------------------------------- Set down a word,which you want to search('#' to quit...): cat ---------------------------------------------- cat n. small furry domesticated animal often kept as a pet or for catching mice ---------------------------------------------- Set down a word,which you want to search('#' to quit...): # 查询完毕... ************************************************** * 1:Query_Word 2:History_Record 3.Quit * ************************************************** please choose: 2 name date word dashuaibi Wed Oct 14 09:23:25 2020 dog dashuaibi Wed Oct 14 09:23:28 2020 cat ************************************************** * 1:Query_Word 2:History_Record 3.Quit * ************************************************** please choose: 3 linux@ubuntu:~/Level8/day3$
linux@ubuntu:~/Level8/day3$ ./client Client staring...OK! ************************************************** * 1:Register 2:Login 3.Quit * ************************************************** please choose: 2 User name: root PIN : 1 Login Success! ************************************************** * WELCOME BACK MR.ROOT! * * 1:Query_Word 2:History_Record 3.Quit * ************************************************** please choose: 2 name password zhangsan 123 lisi 234 wangwu 234 wangba 123 zhaoba 123 root 1 dashuaibi 123 Witch one do you want to search? dashuaibi name date word dashuaibi Wed Oct 14 09:23:25 2020 dog dashuaibi Wed Oct 14 09:23:28 2020 cat ************************************************** * WELCOME BACK MR.ROOT! * * 1:Query_Word 2:History_Record 3.Quit * ************************************************** please choose: 3 linux@ubuntu:~/Level8/day3$
本次使用的字典是 英-英 字典,与服务器端存储在同一文件夹下,文件名为:dict.txt
附链接:http://ku-yufeng.synology.me:5801/Linux/词典项目专用/