Browse Source

项目用到的知识点案例

yaozheng0922 4 months ago
parent
commit
34fe0312d1

BIN
example/bind


+ 17 - 0
example/bind.cc

@@ -0,0 +1,17 @@
+#include <iostream>
+#include <string>
+#include <functional>
+
+void print(const std::string& s, int num)
+{
+    std::cout << s << " " << num << std::endl;
+}
+
+int main()
+{
+    print("nihao", 10);
+    auto func = std::bind(print, "nihao", std::placeholders::_1);
+    func(20);
+
+    return 0;
+}

BIN
example/json_serialize


+ 71 - 0
example/json_serialize.cc

@@ -0,0 +1,71 @@
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <jsoncpp/json/json.h>
+using std::cout;
+using std::endl;
+
+/*使用json完成数据的序列化工作*/
+std::string serialize()
+{
+    // 1. 将需要序列化的数据存储在Json::Value对象中
+    Json::Value root;
+    root["姓名"] = "小明";
+    root["年龄"] = 18;
+    root["成绩"].append(80);  //成绩是数组类型
+    root["成绩"].append(90);
+    root["成绩"].append(100);
+    // 2. 实例化StreamWriterBuilder工厂类对象
+    Json::StreamWriterBuilder swb;
+    // 3. 使用StreamWriterBuilder工厂类对象实例化StreamWriter对象
+    Json::StreamWriter *sw = swb.newStreamWriter();
+    // 4. 使用StreamWriter对象完成Json::Value中数据的序列化工作,并将序列化结果存放到ss中
+    std::stringstream ss;
+    int n = sw->write(root, &ss);
+    if(n != 0)
+    {
+        cout << "json serialize fail" << endl;
+        delete sw;
+        return "";  
+    }
+    
+    delete sw;
+    return ss.str();
+}
+
+/*使用Json完成序列化数据的反序列化工作*/
+void deserialize(const std::string &str)
+{
+    // 1. 实例化一个CharReaderBuilder工厂类对象
+    Json::CharReaderBuilder crb;
+    // 2. 使用CharReaderBuilder对象实例化一个CharReader对象
+    Json::CharReader *cr = crb.newCharReader();
+    // 3. 创建一个Json::Value对象,用于保存json格式字符串反序列化后的结果
+    Json::Value root;
+    // 4. 使用CharReader对象完成json格式字符串的反序列化工作
+    std::string errmsg;
+    bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), &root, &errmsg);
+    if(ret == false)
+    {
+        cout << "json deserialize fail: " << errmsg << endl;
+        delete cr;
+        return;
+    }
+    // 5. 依次打印Json::Value中的数据
+    cout << "姓名: " << root["姓名"].asString() << endl;
+    cout << "年龄: " << root["年龄"].asInt() << endl; 
+    int size = root["成绩"].size();
+    for(int i = 0; i < size; i++)
+    {
+        cout << "成绩: " << root["成绩"][i].asFloat() << endl;
+    }
+}
+
+int main()
+{
+    std::string str = serialize();
+    cout << str << endl;
+    deserialize(str);
+    
+    return 0;
+}

+ 40 - 0
example/jsoncpp.hpp

@@ -0,0 +1,40 @@
+#include <jsoncpp/json/json.h>
+
+/*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();
+};
+/*序列化接口*/
+class JSON_API StreamWriter
+{
+    virtual int write(Value const &root, std::ostream *sout) = 0;
+}; 
+class JSON_API StreamWriterBuilder : public StreamWriter::Factory
+{
+    virtual StreamWriter *newStreamWriter() const;
+};
+/*反序列化接口*/
+class JSON_API CharReader
+{
+    virtual bool parse(char const *beginDoc, char const *endDoc,
+                       Value *root, std::string *errs) = 0;
+};
+class JSON_API CharReaderBuilder : public CharReader::Factory
+{
+    virtual CharReader *newCharReader() const;
+};

+ 14 - 0
example/makefile

@@ -0,0 +1,14 @@
+all:wsserver json_serialize mysql_connect
+
+wsserver:wsserver.cc
+	g++ -o $@ $^ -std=c++11 -lpthread -lboost_system
+
+json_serialize:json_serialize.cc
+	g++ -o $@ $^ -std=c++11 -ljsoncpp
+
+mysql_connect:mysql_connect.cc
+	g++ -o $@ $^ -std=c++11 -lmysqlclient -L/usr/lib64/mysql/
+
+.PHONY:clean
+clean:
+	rm -f wsserver json_serialize mysql_connect

+ 89 - 0
example/mysql_c_api.hpp

@@ -0,0 +1,89 @@
+#include <mysql/mysql.h>
+
+// Mysql操作句柄初始化
+// 参数说明:
+// mysql为空则动态申请句柄空间进⾏初始化
+// 返回值: 成功返回句柄指针, 失败返回NULL
+MYSQL *mysql_init(MYSQL *mysql);
+
+// 连接mysql服务器
+// 参数说明:
+// mysql--初始化完成的句柄
+// host---连接的mysql服务器的地址
+// user---连接的服务器的⽤⼾名
+// passwd-连接的服务器的密码
+// db ----默认选择的数据库名称
+// port---连接的服务器的端⼝: 默认0是3306端⼝
+// unix_socket---通信管道⽂件或者socket⽂件,通常置NULL
+// client_flag---客⼾端标志位,通常置0
+// 返回值:成功返回句柄指针,失败返回NULL
+MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db,
+                                         unsigned int port, const char *unix_socket, unsigned long client_flag);
+
+// 设置当前客⼾端的字符集
+// 参数说明:
+// mysql--初始化完成的句柄
+// csname--字符集名称,通常:"utf8"
+// 返回值:成功返回0, 失败返回⾮0
+int mysql_set_character_set(MYSQL *mysql, const char *csname);
+
+// 选择操作的数据库
+// 参数说明:
+// mysql--初始化完成的句柄
+// db-----要切换选择的数据库名称
+// 返回值:成功返回0, 失败返回⾮0
+int mysql_select_db(MYSQL *mysql, const char *db);
+
+// 执⾏sql语句
+// 参数说明:
+// mysql--初始化完成的句柄
+// stmt_str--要执⾏的sql语句
+// 返回值:成功返回0, 失败返回⾮0
+int mysql_query(MYSQL *mysql, const char *stmt_str);
+
+// 保存查询结果到本地
+// 参数说明:
+// mysql--初始化完成的句柄
+// 返回值:成功返回结果集的指针, 失败返回NULL
+MYSQL_RES *mysql_store_result(MYSQL *mysql);
+
+// 获取结果集中的⾏数
+// 参数说明:
+// result--保存到本地的结果集地址
+// 返回值:结果集中数据的条数
+uint64_t mysql_num_rows(MYSQL_RES *result);
+
+// 获取结果集中的列数
+// 参数说明:
+// result--保存到本地的结果集地址
+// 返回值:结果集中每⼀条数据的列数
+unsigned int mysql_num_fields(MYSQL_RES *result);
+
+// 获取结果集中的列属性信息
+// 参数说明:
+// result--保存到本地的结果集地址
+// 返回值:结果集中每⼀条数据的列数
+MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)
+MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)
+
+// 遍历结果集, 并且这个接⼝会保存当前读取结果位置,每次获取的都是下⼀条数据
+// 参数说明:
+// result--保存到本地的结果集地址
+// 返回值:实际上是⼀个char **的指针,将每⼀条数据做成了字符串指针数组
+// row[0]-第0列 row[1]-第1列 ...
+MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
+
+// 释放结果集
+// 参数说明:
+// result--保存到本地的结果集地址
+void mysql_free_result(MYSQL_RES *result);
+
+// 关闭数据库客⼾端连接,销毁句柄
+// 参数说明:
+// mysql--初始化完成的句柄
+void mysql_close(MYSQL *mysql);
+
+// 获取mysql接⼝执⾏错误原因
+// 参数说明:
+// mysql--初始化完成的句柄
+const char *mysql_error(MYSQL *mysql);

BIN
example/mysql_connect


+ 109 - 0
example/mysql_connect.cc

@@ -0,0 +1,109 @@
+#include <iostream>
+#include <string>
+#include <mysql/mysql.h>
+using std::cout;
+using std::endl;
+
+int main()
+{
+    // 1. 初始化mysql句柄
+    // MYSQL *mysql_init(MYSQL *mysql)
+    MYSQL *mysql = mysql_init(nullptr);
+    if(mysql == nullptr)
+    {
+        cout << "mysql init failed" << endl;
+        return -1;
+    }
+
+    // 2. 连接mysql数据库
+    // MYSQL *mysql_real_connect(...)
+    const std::string host = "127.0.0.1";
+    const std::string user = "thj";
+    const std::string password = "Abcd1234@";
+    const std::string db = "gobang";
+    unsigned int port = 4106;
+    mysql = mysql_real_connect(mysql, host.c_str(), user.c_str(), password.c_str(), db.c_str(), port, nullptr, 0);
+    if(mysql == nullptr)
+    {
+        cout << "connection mysql server failed" << endl;
+        mysql_close(mysql);
+        return -1;
+    }
+
+    // 3. 设置客户端字符集
+    // int mysql_set_character_set(MYSQL *mysql, const char *csname)
+    if (mysql_set_character_set(mysql, "utf8") != 0)
+    {
+        cout << "set client character failed: " << mysql_error(mysql) << endl;
+    }
+
+    // 4. 选择要操作的数据库
+    // int mysql_select_db(MYSQL *mysql, const char *db)
+    // mysql_select_db(mysql, db.c_str());
+
+    // 5. 执行sql语句 -- 增删改
+    // int mysql_query(MYSQL *mysql, const char *stmt_str)
+    if(mysql_query(mysql, "insert into user values(null, '张三', 18, '11122223333')") != 0)
+    {
+        cout << "sql query failed: " << mysql_error(mysql) << endl;
+    }
+
+    // 6. 执行sql语句 -- 查询
+    if (mysql_query(mysql, "select * from user") != 0)
+    { 
+        cout << "sql query failed: " << mysql_error(mysql) << endl;
+    }
+    // 6.1 将查询结果转储到本地
+    // MYSQL_RES *mysql_store_result(MYSQL *mysql)
+    MYSQL_RES *res = mysql_store_result(mysql);
+    if(res == nullptr)
+    {
+        cout << "store query result failed: " << mysql_error(mysql) << endl;
+        mysql_close(mysql);
+        return -1;
+    }
+    // 6.2 获取结果集的行数与列数
+    // uint64_t mysql_num_rows(MYSQL_RES *result)
+    // unsigned int mysql_num_fields(MYSQL_RES *result)
+    int rowCount = mysql_num_rows(res);
+    int colCount = mysql_num_fields(res);
+    // 6.3 打印结果集中的列属性信息
+    // MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result) 一次获取一列
+    // MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result) 一次获取全部
+    for(int i = 0; i < colCount; i++)
+    {
+        // 自动迭代
+        MYSQL_FIELD *field = mysql_fetch_field(res);
+        cout << field->name << '\t';
+    }
+    cout << endl;
+    // 一次获取全部列字段的属性信息,然后分别打印
+    // MYSQL_FIELD *total_fields = mysql_fetch_fields(res);
+    // for(int i = 0; i < colCount; i++)
+    // {
+    //     cout << total_fields[i].name << '\t';
+    // }
+    // cout << endl;
+
+    // 6.4 打印结果集中的行内容
+    // MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
+    for(int i = 0; i < rowCount; i++)
+    {
+        // 一行的所有内容 -- 自动迭代
+        MYSQL_ROW row = mysql_fetch_row(res);
+        for(int j = 0; j < colCount; j++)
+        {
+            // 一行内容中的某一列的内容
+            cout << row[j] << '\t';
+        }
+        cout << endl;
+    }
+
+   // 7. 释放结果集
+   mysql_free_result(res);
+
+   // 8. 关闭mysql连接
+   mysql_close(mysql);
+
+    return 0;
+}

+ 205 - 0
example/websocketpp.hpp

@@ -0,0 +1,205 @@
+#include <websocketpp/server.hpp>
+#include <websocketpp/config/asio_no_tls.hpp>
+
+namespace websocketpp
+{
+    typedef lib::weak_ptr<void> connection_hdl;
+    template <typename config>
+    class endpoint : public config::socket_type
+    {
+        typedef lib::shared_ptr<lib::asio::steady_timer> timer_ptr;
+        typedef typename connection_type::ptr connection_ptr;
+        typedef typename connection_type::message_ptr message_ptr;
+        typedef lib::function<void(connection_hdl)> open_handler;
+        typedef lib::function<void(connection_hdl)> close_handler;
+        typedef lib::function<void(connection_hdl)> http_handler;
+        typedef lib::function<void(connection_hdl, message_ptr)>
+            message_handler;
+        /* websocketpp::log::alevel::none 禁⽌打印所有⽇志*/
+        void set_access_channels(log::level channels);   /*设置⽇志打印等级*/
+        void clear_access_channels(log::level channels); /*清除指定等级的⽇志*/
+        /*设置指定事件的回调函数*/
+        void set_open_handler(open_handler h);       /*websocket握⼿成功回调处理函数*/
+        void set_close_handler(close_handler h);     /*websocket连接关闭回调处理函数*/
+        void set_message_handler(message_handler h); /*websocket消息回调处理函数*/
+        void set_http_handler(http_handler h);       /*http请求回调处理函数*/
+        /*发送数据接⼝*/
+        void send(connection_hdl hdl, std::string &payload,
+                  frame::opcode::value op);
+        void send(connection_hdl hdl, void *payload, size_t len,
+                  frame::opcode::value op);
+        /*关闭连接接⼝*/
+        void close(connection_hdl hdl, close::status::value code, std::string &reason);
+        /*获取connection_hdl 对应连接的connection_ptr*/
+        connection_ptr get_con_from_hdl(connection_hdl hdl);
+        /*websocketpp基于asio框架实现,init_asio⽤于初始化asio框架中的io_service调度
+        器*/
+        void init_asio();
+        /*设置是否启⽤地址重⽤*/
+        void set_reuse_addr(bool value);
+        /*设置endpoint的绑定监听端⼝*/
+        void listen(uint16_t port);
+        /*对io_service对象的run接⼝封装,⽤于启动服务器*/
+        std::size_t run();
+        /*websocketpp提供的定时器,以毫秒为单位*/
+        timer_ptr set_timer(long duration, timer_handler callback);
+    };
+    template <typename config>
+    class server : public endpoint<connection<config>, config>
+    {
+        /*初始化并启动服务端监听连接的accept事件处理*/
+        void start_accept();
+    };
+    template <typename config>
+    class connection
+        : public config::transport_type::transport_con_type,
+          public config::connection_base
+    {
+        /*发送数据接⼝*/
+        error_code send(std::string &payload, frame::opcode::value
+                                                  op = frame::opcode::text);
+        /*获取http请求头部*/
+        std::string const &get_request_header(std::string const &key)
+            /*获取请求正⽂*/
+            std::string const &get_request_body();
+        /*设置响应状态码*/
+        void set_status(http::status_code::value code);
+        /*设置http响应正⽂*/
+        void set_body(std::string const &value);
+        /*添加http响应头部字段*/
+        void append_header(std::string const &key, std::string const &val);
+        /*获取http请求对象*/
+        request_type const &get_request();
+        /*获取connection_ptr 对应的 connection_hdl */
+        connection_hdl get_handle();
+    };
+    namespace http
+    {
+        namespace parser
+        {
+            class parser
+            {
+                std::string const &get_header(std::string const &key);
+            }; 
+            class request : public parser
+            {
+                /*获取请求⽅法*/
+                std::string const &get_method();
+                /*获取请求uri接⼝*/
+                std::string const &get_uri();
+            };
+        }
+    };
+    namespace message_buffer
+    {
+        /*获取websocket请求中的payload数据类型*/
+        frame::opcode::value get_opcode();
+        /*获取websocket中payload数据*/
+        std::string const &get_payload();
+    };
+    namespace log
+    {
+        struct alevel
+        {
+            static level const none = 0x0;
+            static level const connect = 0x1;
+            static level const disconnect = 0x2;
+            static level const control = 0x4;
+            static level const frame_header = 0x8;
+            static level const frame_payload = 0x10;
+            static level const message_header = 0x20;
+            static level const message_payload = 0x40;
+            static level const endpoint = 0x80;
+            static level const debug_handshake = 0x100;
+            static level const debug_close = 0x200;
+            static level const devel = 0x400;
+            static level const app = 0x800;
+            static level const http = 0x1000;
+            static level const fail = 0x2000;
+            static level const access_core = 0x00003003;
+            static level const all = 0xffffffff;
+        };
+    }
+    namespace http
+    {
+        namespace status_code
+        {
+            enum value
+            {
+                uninitialized = 0,
+                continue_code = 100,
+                switching_protocols = 101,
+                ok = 200,
+                created = 201,
+                accepted = 202,
+                non_authoritative_information = 203,
+                no_content = 204,
+                reset_content = 205,
+                partial_content = 206,
+                multiple_choices = 300,
+                moved_permanently = 301,
+                found = 302,
+                see_other = 303,
+                not_modified = 304,
+                use_proxy = 305,
+                temporary_redirect = 307,
+                bad_request = 400,
+                unauthorized = 401,
+                payment_required = 402,
+                forbidden = 403,
+                not_found = 404,
+                method_not_allowed = 405,
+                not_acceptable = 406,
+                proxy_authentication_required = 407,
+                request_timeout = 408,
+                conflict = 409,
+                gone = 410,
+                length_required = 411,
+                precondition_failed = 412,
+                request_entity_too_large = 413,
+                request_uri_too_long = 414,
+                unsupported_media_type = 415,
+                request_range_not_satisfiable = 416,
+                expectation_failed = 417,
+                im_a_teapot = 418,
+                upgrade_required = 426,
+                precondition_required = 428,
+                too_many_requests = 429,
+                request_header_fields_too_large = 431,
+                internal_server_error = 500,
+                not_implemented = 501,
+                bad_gateway = 502,
+                service_unavailable = 503,
+                gateway_timeout = 504,
+                http_version_not_supported = 505,
+                not_extended = 510,
+                network_authentication_required = 511
+            };
+        }
+    }
+    namespace frame
+    {
+        namespace opcode
+        {
+            enum value
+            {
+                continuation = 0x0,
+                text = 0x1,
+                binary = 0x2,
+                rsv3 = 0x3,
+                rsv4 = 0x4,
+                rsv5 = 0x5,
+                rsv6 = 0x6,
+                rsv7 = 0x7,
+                close = 0x8,
+                ping = 0x9,
+                pong = 0xA,
+                control_rsvb = 0xB,
+                control_rsvc = 0xC,
+                control_rsvd = 0xD,
+                control_rsve = 0xE,
+                control_rsvf = 0xF,
+            };
+        }
+    }
+}

BIN
example/wsserver


+ 57 - 0
example/wsserver.cc

@@ -0,0 +1,57 @@
+#include <iostream>
+#include <string>
+#include <functional>
+#include <websocketpp/server.hpp>
+#include <websocketpp/config/asio_no_tls.hpp>
+using std::cout;
+using std::endl;
+
+typedef websocketpp::server<websocketpp::config::asio> wsserver_t;
+
+void http_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {
+    wsserver_t::connection_ptr conn = srv->get_con_from_hdl(hdl);
+    std::cout << "body: " << conn->get_request_body() << std::endl;
+    websocketpp::http::parser::request req = conn->get_request();
+    std::cout << "method: " << req.get_method() << std::endl;
+    std::cout << "uri: " << req.get_uri() << std::endl;
+
+    // 响应一个hello world页面
+    std::string body = "<html><body><h1>Hello World</h1></body></html>";
+    conn->set_body(body);
+    conn->append_header("Content-Type", "text/html");
+    conn->set_status(websocketpp::http::status_code::ok);
+}
+void wsopen_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {
+    cout << "websocket握手成功" << std::endl;
+}
+void wsclose_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {
+    cout << "websocket连接关闭" << endl;
+}
+void wsmessage_callback(wsserver_t *srv, websocketpp::connection_hdl hdl, wsserver_t::message_ptr msg) {
+    wsserver_t::connection_ptr conn = srv->get_con_from_hdl(hdl);
+    cout << "wsmsg: " << msg->get_payload() << endl;
+    std::string rsp = "[client]# " + msg->get_payload();
+    conn->send(rsp, websocketpp::frame::opcode::text);
+}
+int main()
+{
+    // 1. 实例化server对象
+    wsserver_t wssrv;
+    // 2. 设置日志等级
+    wssrv.set_access_channels(websocketpp::log::alevel::none);
+    // 3. 初始化asio调度器
+    wssrv.init_asio();
+    // 4. 设置回调函数
+    wssrv.set_http_handler(std::bind(http_callback, &wssrv, std::placeholders::_1));
+    wssrv.set_open_handler(std::bind(wsopen_callback, &wssrv, std::placeholders::_1));
+    wssrv.set_close_handler(std::bind(wsclose_callback, &wssrv, std::placeholders::_1));
+    wssrv.set_message_handler(std::bind(wsmessage_callback, &wssrv, std::placeholders::_1, std::placeholders::_2));
+    // 5. 设置监听端口
+    wssrv.listen(8080);
+    wssrv.set_reuse_addr(true);
+    // 6. 开始获取新连接
+    wssrv.start_accept();
+    // 7. 启动服务器
+    wssrv.run();
+    return 0; 
+}