简介:
【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; }