简介:
【1】数据:
学生信息:姓名name + 账号account + 分数score
登录信息:账号account + 密码password(学生、管理员)
【2】C/S模型,使用fork实现多进程交互
【3】Client:
1)登录:学生登录,管理员登陆
2)管理员:修改密码、添加学生信息、删除学生信息、查找学生信息(指定account、所有)、修改学生成绩
3)学生:修改密码、查看本人信息、查看指定account学生信息、查看所有学生信息
【4】Server:
1)登录验证
2)密码修改
3)增/删学生信息
4)查找
5)修改
实现:
【1】环境:
数据库使用:MySQL
系统:Ubuntu 16.04 g++ (最新版)
编译命令:g++ name.cpp -o a -std=c++11 `mysql_config --cflags --libs`
【2】数据库:三个表
student :学生成绩(id,name,account,score)
login_student :学生登录(id,account,password)
login_manager :管理员(id,account,password)
###数据准本的txt,写了个程序(cpp)将txt读到了数据库里,由于个人练习,仅使用了1个管理员+3个学生
【3】功能请求编码:在c/s传输中,使用char[]进行接收发送,并且本次练习中,功能较少,使用char[0]进行功能编号
‘0’‘1’:登录
'a'-'f':管理员请求
‘A'-'D':学生请求
//客户端发送格式 管理员登录:0account password 学生登录:1account password 管理员功能: 修改密码:aaccount newpwd 增加学生信息:bname account pwd score 删除:caccount 查找指定account:daccount 查找所有:e 修改分数:faccount newscore 学生功能: 修改密码:Aaccount pwd 查看自己:Baccount 查看他人:Caccount 查看所有:D //服务端发送格式 //非查找 “1” 成功 “0” 失败 //查找 返回结果集
【4】流程
客户端:
登录选择:0 1
输入账号密码
登录验证:send recv,收到“1”登录成功,否则失败
功能显示:0显示管理员功能 1显示学生功能 q退出
输入:a-f 或 A-D
执行对应功能,有输入的输入对应数据,send recv
结果验证:执行成功或者有数据返回,成功输出成功,有数据就输出数据
转到功能显示
服务器端:
数据库初始化,套接字初始化
收到连接请求,fork子进程处理连接,主进程继续accept
子进程:对recv收到的数据进行处理,构建sql查询语句,调用mysql api执行,对返回结果验证,send
代码:
#数据,0是id,自动增长 0 guanliyuan 123456 0 hzk 111111 0 abc 222222 0 xyz 333333 0 hzk hzk 240 0 abc abc 220 0 xyz xyz 230
//从txt读取数据至数据库中 #include <iostream> #include <mysql/mysql.h> #include <string> #include <cstring> #include <fstream> using namespace std; //read the data from "data.txt" //write the data to database int main(int argc,char** argv){ MYSQL conn; mysql_init(&conn); if(mysql_real_connect(&conn,"localhost","root","961225","Sample", 0,NULL,CLIENT_FOUND_ROWS)){ cout<<"connect sc \n"; } else{ cout<<"fail \n"; mysql_close(&conn); return 0; } ifstream in("data.txt"); //default : one manager,three students, int a=1,b=3,c=3; if(argc==4){ a=atoi(argv[1]); b=atoi(argv[2]); c=atoi(argv[3]); } int i,res; int c1,c4; string c2,c3; for(i=0;i<a;++i){ in>>c1>>c2>>c3; string tmp("insert into login_teacher values("); tmp+="0,'"+c2+"','"+c3+"')"; res=mysql_query(&conn,tmp.c_str()); if(res) cout<<"error \n"; else cout<<"ok \n"; } for(i=0;i<b;++i){ in>>c1>>c2>>c3; string tmp("insert into login_student values("); tmp+="0,'"+c2+"','"+c3+"')"; res=mysql_query(&conn,tmp.c_str()); if(res) cout<<"error \n"; else cout<<"ok \n"; } for(i=0;i<c;++i){ in>>c1>>c2>>c3>>c4; string tmp("insert into student values("); tmp+="0,'"+c2+"','"+c3+"',"+to_string(c4)+")"; res=mysql_query(&conn,tmp.c_str()); if(res) cout<<"error \n"; else cout<<"ok \n"; } in.close(); mysql_close(&conn); return 0; }
//客户端 #include <iostream> #include <string> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <cstdlib> #include <cstring> using std::cout; using std::cin; using std::string; using std::to_string; using std::endl; const unsigned int port=8888; void menu(int cho){ if(cho==0){//teacher cout<<"----------Teacher------------\n"; cout<<"a.Change password \n"; cout<<"b.Add student information \n"; cout<<"c.Del student information with account \n"; cout<<"d.Find someone with account \n"; cout<<"e.Find all \n"; cout<<"f.Modify someone with account and score \n"; } else{ cout<<"----------Student------------\n"; cout<<"A.Change password \n"; cout<<"B.Find self \n"; cout<<"C.Find someone with account \n"; cout<<"D.Find all \n"; cout<<"E.score is error with right score \n"; } cout<<"q.exit \n"; cout<<"-----------------------------\n"; cout<<"Input:"; } void recv_send(int s,string acc,int cho){ string name,account,pwd; int score; while(1){ menu(cho); char buf[100]={0}; //cin send recv display cin>>buf[0]; if(buf[0]=='q') break; if(cho==0){ switch(buf[0]){ case 'a': cout<<"New password:"; cin>>pwd; pwd=acc+' '+pwd; strcat(buf,pwd.c_str()); break; case 'b': cout<<"New student info:name,account,password,score \n"; cin>>name>>account>>pwd>>score; name+=' '+account+' '+pwd+' '+to_string(score); strcat(buf,name.c_str()); break; case 'c': cout<<"Deleted account:"; cin>>account; strcat(buf,account.c_str()); break; case 'd': cout<<"Found account:"; cin>>account; strcat(buf,account.c_str()); break; case 'e': break; case 'f': cout<<"Modified score:account,score \n"; cin>>account>>score; account+=' '+to_string(score); strcat(buf,account.c_str()); break; default: cout<<"error input,continue. \n";continue; } } else{ switch(buf[0]){ case 'A': cout<<"New password:"; cin>>pwd; pwd=acc+' '+pwd; strcat(buf,pwd.c_str()); break; case 'B': strcat(buf,acc.c_str()); break; case 'C': cout<<"Found account:"; cin>>account; strcat(buf,account.c_str()); break; case 'D': break; //case 'E': cout<<"Error information!right score is:"; // cin>>score; // account=acc+' '+to_string(score); // strcat(buf,account.c_str()); // break; default: cout<<"error input,continue. \n";continue; } } send(s,buf,strlen(buf)+1,0); char buff[1024]={0}; recv(s,buff,1024,0); switch(buf[0]){ case 'a':case 'b':case 'c':case 'f':case 'A':case 'E': if( buff[0]=='1' ) cout<<"Completed \n"; else cout<<"Failed \n"; break; case 'd':case 'e':case 'B':case 'C':case 'D': for(int i=0;i<strlen(buff);++i) cout<<buff[i]; cout<<endl; break; } } } void deal(int s,const struct sockaddr_in& addr){ int err=connect(s,(struct sockaddr*)&addr,sizeof(addr)); //safe //login int cho; cout<<"Choose your card:teacher 0,student 1 \nInput:"; cin>>cho; string account,password; int ret; while(1){ cout<<"\nAccount:"; cin>>account; cout<<"Password:"; cin>>password; string buf(""); buf+=cho+'0'; buf+=account+' '+password; send(s,buf.c_str(),buf.length()+1,0); char buff[100]={0}; recv(s,buff,100,0); if( strcmp(buff,"1") ==0){ cout<<"Login sc \n"; ret=1; break; } else{ cout<<"Login fail \ncontinue login?('y' or 'n')\nInput"; char c; cin>>c; if(c!='y'){ ret=3; break; } } } if(ret==1) recv_send(s,account,cho); else cout<<"exit\n"; } int main(int argc,char** argv){ int s=socket(AF_INET,SOCK_STREAM,0); //safe sockaddr_in addr; bzero(&addr,sizeof(addr)); addr.sin_family=AF_INET; addr.sin_port=htons(port); addr.sin_addr.s_addr=htonl(INADDR_ANY); deal(s,addr); close(s); return 0; }
//服务器端 #include <iostream> #include <string> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <cstdlib> #include <cstring> #include <vector> #include <mysql/mysql.h> using std::vector; using std::cout; using std::cin; using std::string; using std::to_string; using std::endl; const unsigned int port=8888; const unsigned int backlog=100; MYSQL conn; int Init_mysql(){ mysql_init(&conn); if(mysql_real_connect(&conn,"localhost","root","961225","Sample", 0,NULL,CLIENT_FOUND_ROWS)){ cout<<"connect sc \n"; } else{ cout<<"fail \n"; mysql_close(&conn); return -1; } return 0; } int Socket(){ int s=socket(AF_INET,SOCK_STREAM,0); //safe sockaddr_in addr; bzero(&addr,sizeof(addr)); addr.sin_family=AF_INET; addr.sin_port=htons(port); addr.sin_addr.s_addr=htonl(INADDR_ANY); int res=bind(s,(struct sockaddr*)&addr,sizeof(addr)); //safe res=listen(s,backlog); //safe return s; } vector<string> split(const char* buf){ vector<string> res; int i=0; int len=strlen(buf); string tmp; while(i<len){ tmp=""; for(;i<len && buf[i]!=' ';++i) tmp+=buf[i]; res.push_back(tmp); ++i; } return res; } void send(int c,char cho,char* buf){ vector<string> res; string str=""; char buffer[1024]={0}; switch(cho){ case '0':case '1': res=split(buf); str="select id from login_"; if(cho=='0') str+="teacher "; else str+="student "; str+="where account='"+res[0]+"' and password='"+res[1]+"'"; //exec mysql_query(&conn,str.c_str()); { MYSQL_RES* ret=mysql_store_result(&conn); int rows=mysql_num_rows(ret); if(rows==0) strcpy(buffer,"0"); else strcpy(buffer,"1"); } break; case 'a':case 'A': res=split(buf); str="update login_"; if(cho=='a') str+="teacher "; else str+="student "; str+="set password='"+res[1]+"' where account='"+res[0]+"'"; cout<<str<<endl; //exec { int res=mysql_query(&conn,str.c_str()); if(res) strcpy(buffer,"0"); else strcpy(buffer,"1"); } break; case 'b': res=split(buf); str="insert into login_student values(0,'"+res[1]+"','"+res[2]+"')"; cout<<str<<endl; //exec { int res=mysql_query(&conn,str.c_str()); if(res){ strcpy(buffer,"0");break;} } str="insert into student values(0,'"+res[0]+"','"+res[1]+"','"+res[3]+"')"; cout<<str<<endl; { int res=mysql_query(&conn,str.c_str()); if(res) strcpy(buffer,"0"); else strcpy(buffer,"1"); } break; case 'c': res=split(buf); str="delete from login_student where account='"+res[0]+"'"; cout<<str<<endl; //exec { int res=mysql_query(&conn,str.c_str()); if(res){ strcpy(buffer,"0");break;} } str="delete from student where account='"+res[0]+"'"; cout<<str<<endl; //exec { int res=mysql_query(&conn,str.c_str()); if(res) strcpy(buffer,"0"); else strcpy(buffer,"1"); } break; case 'd':case 'B':case 'C':case 'e':case 'D': if(cho=='e' || cho=='D') str="select * from student"; else{ res=split(buf); str="select * from student where account='"+res[0]+"'"; } cout<<str<<endl; //exec { mysql_query(&conn,str.c_str()); MYSQL_RES* result=NULL; result=mysql_store_result(&conn); int cols=mysql_num_fields(result); MYSQL_ROW row=NULL; row=mysql_fetch_row(result); strcpy(buffer,"id\tname\taccount\tscore\n"); while(row){ for(int i=0;i<cols;++i){ strcat(buffer,row[i]); strcat(buffer,"\t"); } strcat(buffer,"\n"); row=mysql_fetch_row(result); } mysql_free_result(result); } break; case 'f': res=split(buf); str="update student set score='"+res[1]+"' where account='"+res[0]+"'"; cout<<str<<endl; //exec { int res=mysql_query(&conn,str.c_str()); if(res) strcpy(buffer,"0"); else strcpy(buffer,"1"); } break; //case 'E': } send(c,buffer,strlen(buffer)+1,0); } void recv_send(int c){ while(1){ char buf[100]={0}; recv(c,buf,100,0); send(c,buf[0],&buf[1]); } } void deal(int s){ while(1){ sockaddr_in addr; socklen_t len; int c=accept(s,(struct sockaddr*)&addr,&len); //safe pid_t p=fork(); //safe if(p==0){ close(s); recv_send(c); } else if(p>0){ close(c); } } } int main(int argc,char** argv){ if( Init_mysql()==-1) return -1; int s=Socket(); deal(s); close(s); mysql_close(&conn); return 0; }