音乐播放器拥有注册登录功能,查看所有的音乐列表,也可以听音乐,也可以将音乐添加到自己的喜欢列表。
1 #include<stdio.h> 2 #include<iostream> 3 4 #include<string.h> 5 #include"httplib.h" 6 7 using namespace httplib; 8 using namespace std; 9 10 int g_val=100; 11 12 void Get_CallBackFunc(const Request& req, Response& resp) 13 { 14 printf("%d\n",g_val); 15 cout<<req.method<<endl; 16 printf("i am Get_CallBackFunc\n"); 17 18 const char* lp="<html><h2>hello world!</h2></html>"; 19 resp.set_content(lp,strlen(lp),"text/html"); 20 } 21 22 23 24 int main() 25 { 26 Server http_svr; 27 int a=10; 28 29 http_svr.Get("/abc",Get_CallBackFunc); 30 http_svr.Post("/111",[a](const Request& req,Response& resp){ 31 printf("a:%d\n",a); 32 33 }); 34 //直接访问web里面的文件 35 //逻辑根目录指定为web文件夹 36 http_svr.set_mount_point("/","./web"); 37 http_svr.listen("0.0.0.0",21010); 38 39 return 0; 40 }
1 #include<stdio.h> 2 #include<iostream> 3 #include<jsoncpp/json/json.h> 4 5 using namespace std; 6 7 int main() 8 { 9 10 Json::Value v1; 11 v1["id"]=1; 12 v1["name"]="yyw"; 13 cout<<v1<<endl; 14 15 Json::Value v2; 16 v2["id"]=2; 17 v2["name"]="yy"; 18 cout<<v2<<endl; 19 20 Json::Value v3; 21 v3["v1"]=v1; 22 v3["v2"]=v2; 23 cout<<v3<<endl; 24 25 Json::Value v4; 26 v4.append(v1); 27 v4.append(v2); 28 cout<<v4<<endl; 29 30 for(int i=0;i<2;i++) 31 { 32 cout<<v4[i]["id"]<<":"<<v4[i]["name"]<<endl; 33 } 34 35 //序列化 36 Json::FastWriter w; 37 string json_str=w.write(v4); 38 cout<<json_str<<endl; 39 //反序列化 40 Json::Reader r; 41 Json::Value vv; 42 r.parse(json_str,vv); 43 cout<<vv<<endl; 44 return 0; 45 }
JSON数据格式有三种显示方法:平铺、嵌套、数组形式。
序列化和反序列化:
#include<stdio.h> #include<iostream> #include<jsoncpp/json/json.h> #include<string.h> #include"httplib.h" using namespace httplib; using namespace std; int g_val=100; void Get_CallBackFunc(const Request& req, Response& resp) { printf("%d\n",g_val); cout<<req.method<<endl; printf("i am Get_CallBackFunc\n"); const char* lp="<html><h2>hello world!</h2></html>"; resp.set_content(lp,strlen(lp),"text/html"); } int main() { Server http_svr; http_svr.Get("/abc",Get_CallBackFunc); //发送post请求/login,回调这个表达式 http_svr.Post("/login",[](const Request& req,Response& resp){ cout<<req.body<<endl; //打印正文信息 Json::Value resp_json; resp_json["login_status"]=true; //浏览器返回登录状态 //序列化 //系列化成完整的字符串的内容放到响应的正文中 Json::FastWriter w; resp.body= w.write(resp_json); //告诉浏览器返回的内容就是json串,对json解析 resp.set_header("Content-Type","application/json"); }); //直接访问web里面的文件 //逻辑根目录指定为web文件夹 http_svr.set_mount_point("/","./web"); http_svr.listen("0.0.0.0",21010); return 0; }
1 #pragma once 2 #include"database.hpp" 3 #include<stdio.h> 4 #include<iostream> 5 #include<string> 6 #include"httplib.h" 7 8 #include<jsoncpp/json/json.h> 9 10 using namespace std; 11 12 using namespace httplib; 13 14 #define MUSIC_SVR_IP "0.0.0.0" 15 #define MUSIC_SVR_PORT 18989 16 17 class MusicServer 18 { 19 public: 20 MusicServer() 21 { 22 svr_ip_=MUSIC_SVR_IP; 23 svr_port_=MUSIC_SVR_PORT; 24 db_svr_=NULL; 25 } 26 ~MusicServer() 27 { 28 29 } 30 31 //1.初始化当前类接 32 int InitMusicServer(string ip=MUSIC_SVR_IP,uint16_t port=MUSIC_SVR_PORT) 33 { 34 svr_ip_=ip; 35 svr_port_=port; 36 37 db_svr_=new DataBaseSvr("1.14.165.138","yy","123","music_svr"); 38 if(db_svr_==NULL) 39 { 40 return -1; 41 } 42 return 0; 43 } 44 //2.启动服务的接口 45 int StartMusicServer() 46 { 47 //1.注册个若干个http请求的对应的回调函数 48 /* 49 *请求:{"name":"yy","passwd":"123","email":"123@qq.com","phonenum":"1231"} 50 *响应:{"register_status":"xxxx"} 51 * 52 * 53 * */ 54 http_svr_.Post("/register",[this](const Request& req,Response& resq){ 55 cout<<req.body<<endl; 56 //1.需要将浏览器中的数据持久化(保存在数据库中) 57 // 58 //1.将用户提交的数据进行反序列化,拿到一个json对象 59 Json::Reader r; 60 Json::Value v; 61 r.parse(req.body,v); 62 63 cout<<v["name"]<<endl; 64 cout<<v["passwd"]<<endl; 65 cout<<v["email"]<<endl; 66 cout<<v["phonenum"]<<endl; 67 68 db_svr_->InsertUserInfo(v); 69 }); 70 71 http_svr_.Post("/login",[](const Request& req,Response& resq){ 72 /* 73 *1. 74 *2. 75 *3. 76 * */ 77 cout<<req.body<<endl; 78 79 }); 80 81 //2.设置http服务器静态路径(逻辑根目录) 82 http_svr_.set_mount_point("/","./web"); 83 //3.监听起来 84 http_svr_.listen(svr_ip_.c_str(),svr_port_); 85 } 86 private: 87 //httplib 当中的server对象 88 Server http_svr_; 89 90 string svr_ip_; 91 uint16_t svr_port_; 92 93 //数据库操作模块 94 DataBaseSvr* db_svr_; 95 };
54 http_svr_.Post("/register",[this](const Request& req,Response& resq){ 55 cout<<req.body<<endl; 56 //1.需要将浏览器中的数据持久化(保存在数据库中) 57 // 58 //1.将用户提交的数据进行反序列化,拿到一个json对象 59 Json::Reader r; 60 Json::Value v; 61 r.parse(req.body,v); 62 63 cout<<v["name"]<<endl; 64 cout<<v["passwd"]<<endl; 65 cout<<v["email"]<<endl; 66 cout<<v["phonenum"]<<endl; 67 68 db_svr_->InsertUserInfo(v); 69 });
1 #pragma once 2 #include<stdio.h> 3 #include<unistd.h> 4 #include<iostream> 5 #include<string> 6 7 #include<mysql/mysql.h> 8 #include<jsoncpp/json/json.h> 9 using namespace std; 10 class DataBaseSvr 11 { 12 public: 13 DataBaseSvr(const string& db_host,const string& db_user,const string& db_password,const string& db_name,unsigned int db_port=3306) 14 { 15 mysql_init(&mysql_); 16 db_host_=db_host; 17 db_user_=db_user; 18 db_password_=db_password; 19 db_port_=db_port; 20 db_name_=db_name; 21 } 22 ~DataBaseSvr() 23 { 24 25 } 26 27 int ConnectToMysql() 28 { 29 if(!mysql_real_connect(&mysql_,db_host_.c_str(),db_user_.c_str(),db_password_.c_str(),db_name_.c_str(),db_port_,NULL,CLIENT_FOUND_ROWS)) 30 { 31 cout<<mysql_error(&mysql_)<<endl; 32 return -1; 33 } 34 return 0; 35 } 36 37 //提交上来的对象 38 int InsertUserInfo(const Json::Value& v) 39 { 40 //1.连接数据库 41 if(ConnectToMysql()<0) 42 { 43 return -1; 44 } 45 //2.组织sql语 46 47 string name=v["name"].asString(); 48 string password=v["password"].asString(); 49 string email=v["email"].asString(); 50 string phonenum=v["phonenum"].asString(); 51 52 #define INSERT_USER_INFO "insert into sys_user(user_name,password,email,phone_num) values('%s','%s','%s','%s');" 53 54 char sql[1024]={0}; 55 snprintf(sql,sizeof(sql)-1,INSERT_USER_INFO,name.c_str(),password.c_str(),email.c_str(),phonenum.c_str()); 56 cout<<"sql:"<<sql<<endl; 57 58 //3.继续执行sql 59 //4.返回插入结果给调用者 60 } 61 private: 62 MYSQL mysql_; 63 64 string db_host_; 65 string db_user_; 66 string db_password_; 67 string db_name_; 68 unsigned int db_port_; 69 };
//查询用户是否存在 105 int QueryUserExist(const Json::Value& v) 106 { 107 /* //0 链接 108 if(ConnectToMysql()<0) 109 { 110 return -1; 111 }*/ 112 //1.从json对象当中解析出来 邮箱和密码 113 114 string email = v["email"].asString(); 115 string password = v["password"].asString(); 116 117 //2.使用邮箱作为查询条件在sys_user表当中进行查询(如果没有查找到用户,则返回) 118 #define QUERY_USER "select * from sys_user where email='%s';" 119 char sql[1024] = {0}; 120 snprintf(sql, sizeof(sql) - 1, QUERY_USER, email.c_str()); 121 cout << sql << endl; 122 123 //3.针对查询的结果当中的密码, 进行比对 124 MYSQL_RES* res = NULL; 125 if(ExecuteSql(sql, &res) == false) 126 { 127 return -2; 128 } 129 130 //3.1 针对结果集进行操作, 判断下,结果集当中的行数是否等于1 131 // 等于1, 继续往下执行 132 // 不等1 , 直接返回 133 //my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res); 134 if(mysql_num_rows(res) != 1) 135 { 136 cout << "No Data for sql!, sql is " << sql <<endl; 137 mysql_free_result(res); 138 return -3; 139 } 140 141 //3.2 在结果集当中获取一行数据 142 //MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); 143 // 如果重复调用msyql_fetch_row这个函数, 默认是取下一行的数据 144 MYSQL_ROW row = mysql_fetch_row(res); 145 146 //3.3 比对密码 147 string db_password = row[2]; 148 if(db_password != password ) 149 { 150 return -4; 151 } 152 153 mysql_free_result(res); 154 //4.返回查询结果 155 return atoi(row[0]); 156 }
1 #include"music_player.hpp" 2 void Usage() 3 { 4 cout << "./MusicServer [command key] [command value] ..." << endl; 5 cout << " " << "-ip : svr listen ip" << endl; 6 cout << " " << "-port : svr listen port" << endl; 7 cout << " " << "-db_ip : msyql server ip address" << endl; 8 cout << " " << "-db_port : mysql port" << endl; 9 cout << " " << "-db_user : mysql user" << endl; 10 cout << " " << "-db_passwd : mysql password" << endl; 11 cout << " " << "-db_db : which database " << endl; 12 cout << " " << "-h : show usage" << endl; 13 } 14 15 //通过命令行参数获取ip地址和端口号之类的信息 16 int main(int argc, char* argv[]) 17 { 18 if(argc == 2 && strcmp(argv[1], "-h") == 0) 19 { 20 Usage(); 21 exit(1); 22 } 23 string svr_ip, db_ip, db_user, db_db, db_passwd; 24 uint16_t svr_port, db_port; 25 for(int i = 0; i < argc; i++) 26 { 27 if(strcmp(argv[i], "-ip") == 0 && i + 1 < argc) 28 { 29 svr_ip = argv[i + 1]; 30 } 31 else if(strcmp(argv[i], "-port") == 0 && i + 1 < argc) 32 { 33 svr_port = atoi(argv[i + 1]); 34 } 35 else if(strcmp(argv[i], "-db_ip") == 0 && i + 1 < argc) 36 { 37 db_ip = argv[i + 1]; 38 } 39 else if(strcmp(argv[i], "-db_port") == 0 && i + 1 < argc) 40 { 41 db_port = atoi(argv[i + 1]); 42 } 43 else if(strcmp(argv[i], "-db_user") == 0 && i + 1 < argc) 44 { 45 db_user = argv[i + 1]; 46 } 47 else if(strcmp(argv[i], "-db_db") == 0 && i + 1 < argc) 48 { 49 db_db = argv[i + 1]; 50 } 51 else if(strcmp(argv[i], "-db_passwd") == 0 && i + 1 < argc) 52 { 53 db_passwd = argv[i + 1]; 54 } 55 } 56 cout<<"please check info:"<<endl; 57 cout << "svr_ip: " << svr_ip << endl; 58 cout << "svr_pot: " << svr_port << endl; 59 cout << "db_ip: " << db_ip << endl; 60 cout << "db_port: " << db_port << endl; 61 cout << "db_user: " << db_user << endl; 62 //cout << "db_passwd: " << db_passwd << endl; 63 cout << "db_db: " << db_db << endl; 64 65 //重新输出ip 66 int select = 0; 67 cout << "enter check result: currect input 1, error input 0;" << endl; 68 cout << "[input select]: "; 69 cin >> select; 70 switch(select) 71 { 72 case 0: 73 cout << "plase retry start server.." << endl; 74 break; 75 case 1: 76 { 77 MusicServer* ms = new MusicServer(); 78 if(ms == NULL) 79 { 80 return -1; 81 } 82 83 if(ms->InitMusicServer(db_ip, db_port, db_user, db_passwd, db_db, svr_ip, svr_port) < 0) 84 { 85 return -2; 86 } 87 ms->StartMusicServer(); 88 delete ms; 89 break; 90 } 91 default: 92 printf("input select num error, please input 1(currect) or 0(error)\n"); 93 break; 94 } 95 96 return 0; 97 }
1 #pragma once 2 #include <stdio.h> 3 #include <unistd.h> 4 #include <string.h> 5 #include <openssl/md5.h> 6 #include <iostream> 7 #include <string> 8 #include <unordered_map> 9 10 #include <jsoncpp/json/json.h> 11 #include "httplib.h" 12 13 using namespace std; 14 using namespace httplib; 15 16 typedef enum UserStatus 17 { 18 //不在线 19 OFFLINE = 0, 20 //在线状态 21 ONLINE, 22 }USER_STATUS; 23 24 25 //针对与登录的用户创建的会话信息 26 27 class Session 28 { 29 public: 30 Session() 31 { 32 33 } 34 35 Session(const Json::Value& v, int user_id) 36 { 37 user_id_ = user_id; 38 39 real_str_ += v["email"].asString(); 40 real_str_ += v["password"].asString(); 41 42 us_status_ = ONLINE; 43 } 44 45 ~Session() 46 { 47 48 } 49 50 51 bool CalcMd5() 52 { 53 MD5_CTX ctx; 54 MD5_Init(&ctx); 55 56 //int MD5_Update(MD5_CTX *c, const void *data, unsigned long len); 57 if(MD5_Update(&ctx, real_str_.c_str(), real_str_.size()) != 1) 58 { 59 return false; 60 } 61 62 //int MD5_Final(unsigned char *md, MD5_CTX *c); 63 //md ==> 16字节 64 unsigned char md5[16] = { 0 }; 65 if(MD5_Final(md5, &ctx) != 1) 66 { 67 return false; 68 } 69 70 char tmp[2] = {0}; 71 char buf[32] = {0}; 72 for(int i = 0; i < 16; i++) 73 { 74 sprintf(tmp, "%02x", md5[i]); 75 strncat(buf, tmp, 2); 76 } 77 78 session_id_ = buf; 79 cout << "session_id_" << session_id_ << endl; 80 return true; 81 } 82 83 string& GetSessionID() 84 { 85 //1.计算sessionID 86 CalcMd5(); 87 //2.返回session_id 88 return session_id_; 89 } 90 91 int GetUserId() 92 { 93 return user_id_; 94 } 95 96 private: 97 string session_id_; 98 99 //生成会话ID的源字符串 100 string real_str_; 101 102 int user_id_; 103 104 UserStatus us_status_; 105 };
107 //哈希查找多用户的时刻更快 108 class AllSessionInfo 109 { 110 public: 111 AllSessionInfo() 112 { 113 all_sess_map_.clear(); 114 pthread_mutex_init(&map_lock_, NULL); 115 } 116 117 ~AllSessionInfo() 118 { 119 pthread_mutex_destroy(&map_lock_); 120 } 121 122 void InsertSessionInfo(const string session_id, const Session sess) 123 { 124 pthread_mutex_lock(&map_lock_); 125 all_sess_map_.insert(make_pair(session_id, sess)); 126 pthread_mutex_unlock(&map_lock_); 127 } 128 129 int CheckSession(const Request& req) 130 { 131 /* 132 * 1.通过http请求头当中的 Cookie字段, 获取对应的value(会话ID) 133 * 2.通过会话ID, 在all_sess_map_当中查找, 是否有对应的会话信息 134 * */ 135 string sess_id = req.get_header_value("Cookie"); 136 137 pthread_mutex_lock(&map_lock_); 138 auto iter = all_sess_map_.find(sess_id); 139 if(iter == all_sess_map_.end()) 140 { 141 pthread_mutex_unlock(&map_lock_); 142 return -1; 143 } 144 int user_id = iter->second.GetUserId(); 145 pthread_mutex_unlock(&map_lock_); 146 return user_id; 147 } 148 private: 149 unordered_map<string, Session> all_sess_map_; 150 pthread_mutex_t map_lock_; 151 };
int GetMusic(string sql, Json::Value& resp_json) 161 { 162 MYSQL_RES* res = NULL; 163 if(ExecuteSql(sql, &res) == false) 164 { 165 return -2; 166 } 167 168 int row_nums = mysql_num_rows(res); 169 if(row_nums <= 0) 170 { 171 printf("No data: sql is \"%s\"", sql.c_str()); 172 mysql_free_result(res); 173 return -3; 174 } 175 176 MYSQL_ROW row = mysql_fetch_row(res); 177 Json::Value music_value; 178 while(row != NULL) 179 { 180 //1.保存数据到json当中 181 Json::Value tmp; 182 tmp["id"] = row[0]; 183 tmp["title"] = row[1]; 184 tmp["singer"] = row[2]; 185 tmp["url"] = row[3]; 186 187 music_value.append(tmp); 188 row = mysql_fetch_row(res); 189 } 190 191 resp_json["music"] = music_value; 192 mysql_free_result(res); 193 return 0; 194 } 195 196 197 int GetAllMusic(Json::Value& resp_json) 198 { 199 /* 200 * 1.组织查询的sql语句 201 * 2.调用ExecuteSql函数执行sql语句 202 * 3.检查结果集当中的行数 203 * 4.将获取到的结果集, 进行遍历操作 204 * 4.组织json对象 205 * */ 206 const char* sql = "select * from music;"; 207 return GetMusic(sql, resp_json); 208 } 209 210 211 212 int InsertLoveMusic(const Request& req, int user_id) 213 { 214 /* 215 * 1.通过req当中的正文信息, 获取music_id 216 * 2.使用music_id, user_id组织sql语句 217 * 3.执行sql语句 218 * */ 219 Json::Reader r; 220 Json::Value v; 221 r.parse(req.body, v); 222 223 int music_id = v["music_id"].asInt(); 224 225 #define INSERT_LOVE_MUSIC "insert into love_music(user_id, music_id) values(%d, %d);" 226 char sql[1024] = {0}; 227 snprintf(sql, sizeof(sql) - 1, INSERT_LOVE_MUSIC, user_id, music_id); 228 229 if(ExecuteSql(sql) == false) 230 { 231 return -1; 232 } 233 return 1; 234 } 235 236 int GetLoveMusic(int user_id, Json::Value& resp_json) 237 { 238 /* 239 * 1.组织查询sql 240 * 2.调用GetMusic函数 241 * */ 242 #define GET_LOVE_MUSIC "select * from music where music_id in(select music_id from love_music where user_id=%d);" 243 char sql[1024] = {0}; 244 snprintf(sql, sizeof(sql) - 1, GET_LOVE_MUSIC, user_id); 245 return GetMusic(sql, resp_json); 246 }
http_svr_.Get("/findMusic", [this](const Request& req, Response& resp){ 137 /* 138 * 1.会话校验, 从当前http请求的请求体当中拿到 Cookie对应的value值, 会话ID 139 * 1.1 通过会话ID, 在all_sess_当中查找是否有对应的会话 140 * 找到了, 则认为该用户是登录用户, 就可以做后续查找音乐的操作 141 * 没有找到, 则认为该用户是非登录用户, 则返回status为-1 142 * 2.通过数据库模块在数据表music当中查找音乐信息, 则将查找到的音乐信息组织成为json串 143 * 3.组织应答 144 * */ 145 Json::Value resp_json; 146 int user_id = all_sess_->CheckSession(req); 147 resp_json["status"] = user_id; 148 if(user_id > 0) 149 { 150 /* 1.会话校验成功的逻辑 151 * 2.访问数据库, 获取到数据表music的音乐信息 152 */ 153 db_svr_->GetAllMusic(resp_json); 154 } 155 156 Json::FastWriter w; 157 resp.body = w.write(resp_json); 158 resp.set_header("Content-Type", "application/json"); 159 }); 160 161 http_svr_.Post("/loveMusic", [this](const Request& req, Response& resp){ 162 Json::Value resp_json; 163 int user_id = all_sess_->CheckSession(req); 164 resp_json["status"] = user_id; 165 if(user_id > 0) 166 { 167 cout << "user_id: " << user_id << ", req正文信息:" << req.body << endl; 168 resp_json["status"] = db_svr_->InsertLoveMusic(req, user_id); 169 } 170 171 Json::FastWriter w; 172 resp.body = w.write(resp_json); 173 resp.set_header("Content-Type", "application/json"); 174 }); 175 176 http_svr_.Get("/findLoveMusic", [this](const Request& req, Response& resp){ 177 /* 178 * 1.会话校验,通过会话校验, 如果成功就能获取当前请求的用户ID 179 * 2.查数据库, 当前用户喜欢的音乐 180 * 3.组织json, 将用户喜欢的音乐返回给浏览器 181 * */ 182 Json::Value resp_json; 183 int user_id = all_sess_->CheckSession(req); 184 resp_json["status"] = user_id; 185 if(user_id > 0) 186 { 187 //去数据库当中查询喜欢的音乐 188 db_svr_->GetLoveMusic(user_id, resp_json); 189 } 190 191 Json::FastWriter w; 192 resp.body = w.write(resp_json); 193 resp.set_header("Content-Type", "application/json"); 194 }); 195 //2.设置http服务器静态路径(逻辑根目录) 196 http_svr_.set_mount_point("/","./web"); 197 //3.监听起来 198 http_svr_.listen(svr_ip_.c_str(),svr_port_); 199 }