前置知识的了解
- 前言
- 1.Websocketpp
- 1.1 使用Websocketpp的原因
- 1.2 Websocket常用接口
- 1.3 Websocket搭建服务器流程
- 2.JsonCpp
- 2.1 Json 数据对象类的表示
- 2.2序列化和反序列化的接口
- 2.3 演示代码
- 3.Mysql
- 3.1 演示代码
前言
本文章旨在对五子棋在线对战的代码进行实现的全过程,包括了代码的环境,前置知识的了解,和项目的整体架构。
1.Websocketpp
WebSocket是从HTML5开始⽀持的⼀种⽹⻚端和服务端保持⻓连接的消息推送机制。
1.1 使用Websocketpp的原因
传统的web程序都是一问一答的形式,就是客户端给服务器发送数据,服务器给客户端返回一个相应,这种情况下服务端是被动的一方,他无法主动的给客户端发送数据,
但是这个项目非常依赖消息推送,我们需要服务器主动的给客户端发送消息,如果只是使用原生的http协议,很难满足需求。
基于上述,就产⽣了WebSocket协议。WebSocket更接近于TCP这种级别的通信⽅式,⼀旦连接建⽴完成客⼾端或者服务器都可以主动的向对⽅发送数据。
1.2 Websocket常用接口
1.3 Websocket搭建服务器流程
int main(){
// 1.使用websocketpp库创建服务器
websocketsvr server;
// 2.设置websocketpp库的日志级别
// all表示打印全部级别日志
// none表示什么日志都不打印
server.set_access_channels(websocketpp::log::alevel::none);
// 3.初始化asio
server.init_asio();
// 4.注册http请求的处理函数
server.set_http_handler(bind(&OnHttp, &server, ::_1));
// 5.注册websocket请求的处理函数
server.set_open_handler(bind(&OnOpen, &server, ::_1));
server.set_close_handler(bind(&OnClose, &server, _1));
server.set_message_handler(bind(&OnMessage,&server,_1,_2));
// 6.监听8888端口
server.listen(8888);
// 7.开始接收tcp连接
server.start_accept();
// 8.开始运行服务器
server.run();
return 0;
}
2.JsonCpp
Json 是⼀种数据交换格式,它采⽤完全独⽴于编程语⾔的⽂本格式来存储和表⽰数据
//C语言
char *name = "xx";
int age = 18;
float score[3] = {88.5, 99, 58};
//Json
{
"姓名" : "xx",
"年龄" : 18,
"成绩" : [88.5, 99, 58]
}
[
{"姓名":"小明", "年龄":18, "成绩":[23, 65, 78]},
{"姓名":"小红", "年龄":19, "成绩":[88, 95, 78]}
]
2.1 Json 数据对象类的表示
class Json::Value{
Value &operator=(const Value &other); //Value重载了[]和=,因此所有的赋值和获取数据都可以通过
Value& operator[](const std::string& key); //简单的方式完成 val["name"] = "xx";
Value& operator[](const char* key);
Value removeMember(const char* key); //移除元素
const Value& operator[](ArrayIndex index) const; //val["score"][0]
Value& append(const Value& value); //添加数组元素val["score"].append(88);
ArrayIndex size() const; //获取数组元素个数 val["score"].size();
bool isNull(); //用于判断是否存在某个字段
std::string asString() const; //转string string name = val["name"].asString();
const char* asCString() const; //转char* char *name = val["name"].asCString();
Int asInt() const; //转int int age = val["age"].asInt();
float asFloat() const; //转float float weight = val["weight"].asFloat();
bool asBool() const; //转 bool bool ok = val["ok"].asBool();
};
2.2序列化和反序列化的接口
2.3 演示代码
#include <iostream>
#include <string>
#include <sstream>
#include <jsoncpp/json/json.h>
std::string serialize()
{
// 1.将序列化的数据,存储在Json::Value中
Json::Value root;
root["name"] = "kang";
root["age"] = 22;
root["num"].append(120);
root["num"].append(104);
root["num"].append(111);
// 2.实例化一个StreamWriterBuilder工厂类中
Json::StreamWriterBuilder swb;
// 3.通过StreamWriterBuilder工厂类对象生产一个StreamWriter对象
Json::StreamWriter *sw = swb.newStreamWriter();
// 4.使用StreamWriter对象,对存储在Json::Value中的数据进行序列化
std::stringstream ss;
int ret = sw->write(root, &ss);
if (ret != 0)
{
std::cout << "Json 序列化 faild" << std::endl;
return nullptr;
}
std::cout << ss.str() << std::endl;
delete sw;
return ss.str();
}
void unserialize(const std::string &str)
{
//1.实例化一个CharReaderBuilder工厂类对象
Json::CharReaderBuilder crb;
//2.使用这个工厂类对象生产一个CharReader对象
Json::CharReader *cr=crb.newCharReader();
//3.定义一个Json::Value对象存储解析后的数据
Json::Value root;
std::string error;
//4.使用CharReader对象进行Json格式字符串str的反序列化
//parse(char* start, char* end, Json::Value *val, string *err)
bool ret=cr->parse(str.c_str(),str.c_str()+str.size(),&root,&error);
if(ret==false)
{
std::cout<<"json unserialize failed"<<std::endl;
return ;
}
//5.逐个元素去访问Json::Value的数据
std::cout<<"name: "<<root["name"].asString()<<std::endl;
std::cout<<"age: "<<root["age"].asInt()<<std::endl;
int len=root["num"].size();
for(int i=0;i<len;i++)
{
std::cout<<"num: "<<root["num"][i].asFloat()<<std::endl;
}
delete cr;
}
int main()
{
std::string str=serialize();
unserialize(str);
return 0;
}
3.Mysql
3.1 演示代码
#include <stdio.h>
#include <string.h>
#include <mysql/mysql.h>
#define HOST "127.0.0.1"
#define PORT 3306
#define USER "root"
#define PASS "yangjuntao"
#define DBNAME "gobang"
int main()
{
// 1. 初始化mysql操作句柄
// MYSQL *mysql_init(MYSQL *mysql)
MYSQL *mysql = mysql_init(NULL);
if (mysql == NULL)
{
printf("mysql init failed\n");
return -1;
}
// 2. 连接mysql服务器
// MYSQL *mysql_real_connect(mysql,host,user,pass,dbname,port,unix_socket,flag)
if (mysql_real_connect(mysql, HOST, USER, PASS, DBNAME, PORT, NULL, 0) == NULL)
{
printf("connect mysql server failed : %s \n", mysql_error(mysql));
mysql_close(mysql);
return -1;
}
// 3. 设置客户端的字符集
// int mysql_set_character_set(mysql, "utf8");
if (mysql_set_character_set(mysql, "utf8") != 0)
{
printf("set client character failed : %s\n", mysql_error(mysql));
mysql_close(mysql);
return -1;
}
// 4. 选择想要操作的数据库
// int mysql_select_db(mysql, dbname)
// mysql_select_db(mysql, dbname);
// 5. 执行sql语句
// int mysql_query(MYSQL* mysql,char *sql);
char* sql="insert stu values(null,'kangchu',24,23,25,19);";
// char * sql="updata stu set ch=ch+40 where sn=1;";
// char * sql="delete from stu where sn=1;";
//char *sql = "select * from stu;";
int ret = mysql_query(mysql, sql);
if (ret != 0)
{
printf("%s\n", sql);
printf("mysql query,failed : %s\n", mysql_error(mysql));
mysql_close(mysql);
return -1;
}
// 6. 如果是查询语句则需要保存到本地
// MYSQL_RES *mysql_store_result(MYSQL *mysql)
MYSQL_RES *res = mysql_store_result(mysql);
if (res == NULL)
{
mysql_close(mysql);
return -1;
}
// 7. 获取结果集中的结果条数目
// int mysql_num_rows(MYSQL_RES *result)
// int mysql_num_fields(MYSQL_RES *result)
int num_row = mysql_num_rows(res);
int num_col = mysql_num_fields(res);
// 8. 遍历保存到本地的结果集
// MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
for (int i = 0; i < num_row; i++)
{
MYSQL_ROW row = mysql_fetch_row(res);
for (int i = 0; i < num_col; i++)
{
printf("%s\t", row[i]);
}
printf("\n");
}
// 9. 释放结果集
mysql_free_result(res);
// 10. 关闭连接,释放句柄
mysql_close(mysql);
return 0;
}