C/S模型-多程序-簡易版學生-管理系統(帶資料庫)
簡介:
【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; }