2.1.C++项目:网络版五子棋对战之前置知识

news2024/11/17 10:04:40

文章目录

  • 一、Websocketpp
    • (一)Websocket介绍
    • (二)报文格式
    • (三)Websocketpp介绍
    • (四)Websocketpp使用
      • 1.websocketpp常用接口介绍
      • 2. http/websocket服务器
    • (五)JsonCpp使用

一、Websocketpp

(一)Websocket介绍

WebSocket 是从 HTML5 开始支持的⼀种网页端和服务端保持长 连接的 消息推送机制。

  • 传统的 web 程序都是属于 “一问一答” 的形式,即客户端给服务器发送了⼀个 HTTP 请求,服务器给客户端返回一个 HTTP 响应。这种情况下服务器是属于被动的一方,如果客户端不主动发起请求服务器就无法主动给客户端端响应
  • 像网页即时聊天或者我们做的五子棋游戏这样的程序都是非常依赖 “消息推送” 的, 即需要服务器主动推动消息到客户端。如果只是使用原生的 HTTP 协议,要想实现消息推送⼀般需要通过 “轮询” 的方式实现, 而轮询的成本比较高并且也不能及时的获取到消息的响应。
    基于上述两个问题, 就产生了WebSocket协议。WebSocket 更接近于 TCP 这种级别的通信方式,一旦连接建立完成客户端或者服务器都可以主动的向对方发送数据。
    WebSocket 协议本质上是⼀个基于 TCP 的协议。为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起⼀个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了⼀些附加头信息,通过这个附加头信息完成握手过程并升级协议的过程。
    在这里插入图片描述
    在这里插入图片描述

(二)报文格式

在这里插入图片描述
我们重点关注这几个字段:

  • FIN: WebSocket传输数据以消息为概念单位,一个消息有可能由⼀个或多个帧组成,FIN字段为1表示末尾帧。
  • RSV1~3:保留字段,只在扩展时使⽤,若未启用扩展则应置1,若收到不全为0的数据帧,且未协商扩展则立即终止连接。
  • opcode: 标志当前数据帧的类型
  • 0x0: 表示这是个延续帧,当 opcode 为 0 表⽰本次数据传输采⽤了数据分片,当前收到的帧为其中⼀个分片
  • 0x1: 表示这是文本帧
  • 0x2: 表示这是⼆进制帧
  • 0x3-0x7: 保留,暂未使用
  • 0x8: 表示连接断开
  • 0x9: 表示 ping 帧
  • 0xa: 表示 pong 帧
  • 0xb-0xf: 保留,暂未使⽤
  • mask:表示Payload数据是否被编码,若为1则必有Mask-Key,用于解码Payload数据。仅客户端发送给服务端的消息需要设置。
  • Payload length:数据载荷的长度,单位是字节, 有可能为7位、7+16位、7+64位。假设Payloadlength = x
  • x为0~126:数据的长度为x字节
  • x为126:后续2个字节代表⼀个16位的无符号整数,该无符号整数的值为数据的长度
  • x为127:后续8个字节代表⼀个64位的无符号整数(最高位为0),该⽆符号整数的值为数据的长度
  • Mask-Key:当mask为1时存在,长度为4字节,解码规则: DECODED[i] = ENCODED[i] ^ MASK[i% 4]
  • Payload data: 报文携带的载荷数据

(三)Websocketpp介绍

WebSocketpp是⼀个跨平台的开源(BSD许可证)头部专用C++库,它实现了RFC6455(WebSocket协议)和RFC7692(WebSocketCompression Extensions)。它允许将WebSocket客户端和服务器功能集成到C++程序中。在最常见的配置中,全功能网络I/O由Asio网络库提供。
WebSocketpp的主要特性包括:

  • 事件驱动的接口
  • 支持HTTP/HTTPS、WS/WSS、IPv6
  • 灵活的依赖管理 — Boost库/C++11标准库
  • 可移植性:Posix/Windows、32/64bit、Intel/ARM
  • 线程安全

WebSocketpp同时支持HTTP和Websocket两种网络协议, 比较适用于我们本次的项目,所以我们选用该库作为项目的依赖库用来搭建HTTP和WebSocket服务器。

(四)Websocketpp使用

1.websocketpp常用接口介绍

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 {
70 namespace parser {
71 class parser {
72 std::string const & get_header(std::string const & key)
73 }
74 class request : public parser {
75 /*获取请求⽅法*/
76 std::string const & get_method()
77 /*获取请求uri接⼝*/
78 std::string const & get_uri()
79 };
80 }};
81 
82 namespace message_buffer {
83 /*获取websocket请求中的payload数据类型*/
84 frame::opcode::value get_opcode();
85 /*获取websocket中payload数据*/
86 std::string const & get_payload();
87 };
88 
89 namespace log {
90 struct alevel {
91 static level const none = 0x0;
92 static level const connect = 0x1;
93 static level const disconnect = 0x2;
94 static level const control = 0x4;
static level const frame_header = 0x8;
96 static level const frame_payload = 0x10;
97 static level const message_header = 0x20;
98 static level const message_payload = 0x40;
99 static level const endpoint = 0x80;
100 static level const debug_handshake = 0x100;
101 static level const debug_close = 0x200;
102 static level const devel = 0x400;
103 static level const app = 0x800;
104 static level const http = 0x1000;
105 static level const fail = 0x2000;
106 static level const access_core = 0x00003003;
107 static level const all = 0xffffffff;
108 };
109 }
110 
111 namespace http {
112 namespace status_code {
113 enum value {
114 uninitialized = 0,
115
116 continue_code = 100,
117 switching_protocols = 101,
118
119 ok = 200,
120 created = 201,
121 accepted = 202,
122 non_authoritative_information = 203,
123 no_content = 204,
124 reset_content = 205,
125 partial_content = 206,
126
127 multiple_choices = 300,
128 moved_permanently = 301,
129 found = 302,
130 see_other = 303,
131 not_modified = 304,
132 use_proxy = 305,
133 temporary_redirect = 307,
134
135 bad_request = 400,
136 unauthorized = 401,
137 payment_required = 402,
138 forbidden = 403,
139 not_found = 404,
140 method_not_allowed = 405,
141 not_acceptable = 406,
142 proxy_authentication_required = 407,
143 request_timeout = 408,
144 conflict = 409,
145 gone = 410,
146 length_required = 411,
147 precondition_failed = 412,
148 request_entity_too_large = 413,
149 request_uri_too_long = 414,
150 unsupported_media_type = 415,
151 request_range_not_satisfiable = 416,
152 expectation_failed = 417,
153 im_a_teapot = 418,
154 upgrade_required = 426,
155 precondition_required = 428,
156 too_many_requests = 429,
157 request_header_fields_too_large = 431,
158
159 internal_server_error = 500,
160 not_implemented = 501,
161 bad_gateway = 502,
162 service_unavailable = 503,
163 gateway_timeout = 504,
164 http_version_not_supported = 505,
165 not_extended = 510,
166 network_authentication_required = 511
167 };}}
168 namespace frame {
169 namespace opcode {
170 enum value {
171 continuation = 0x0,
172 text = 0x1,
173 binary = 0x2,
174 rsv3 = 0x3,
175 rsv4 = 0x4,
176 rsv5 = 0x5,
177 rsv6 = 0x6,
178 rsv7 = 0x7,
179 close = 0x8,
180 ping = 0x9,
181 pong = 0xA,
182 control_rsvb = 0xB,
183 control_rsvc = 0xC,
184 control_rsvd = 0xD,
185 control_rsve = 0xE,
186 control_rsvf = 0xF,
187 };}}
188 }

2. http/websocket服务器

使⽤Websocketpp实现⼀个简单的http和websocket服务器:

#include <iostream>
#include <string>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>

typedef websocketpp::server<websocketpp::config::asio> wsserver_t;

void print(const std::string &str)
{
    std::cout << str << std::endl;
}

void http_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {
    //给客户端返回一个hello world的页面
    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;cmake --version
    std::cout << "uri: " << req.get_uri() << std::endl;

    std::string body = "<html><body><h1>Hello World</h1></body></html>";
    //conn->set_body(body);
    //conn->append_header("Content-Type", "text/html");
    conn->set_body(conn->get_request_body());
    conn->set_status(websocketpp::http::status_code::ok);
    wsserver_t::timer_ptr tp = srv->set_timer(5000, std::bind(print, "ive"));
    tp->cancel();//定时任务的取消,会导致定时任务立即被执行
}
void wsopen_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {
    std::cout << "websocket握手成功!!\n";
}
void wsclose_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {
    std::cout << "websocket连接断开!!\n";
}
void wsmsg_callback(wsserver_t *srv, websocketpp::connection_hdl hdl, wsserver_t::message_ptr msg) {
    wsserver_t::connection_ptr conn = srv->get_con_from_hdl(hdl);
    std::cout << "wsmsg: " << msg->get_payload() << std::endl;
    std::string rsp = "client say: " + 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();
    wssrv.set_reuse_addr(true);
    //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(wsmsg_callback, &wssrv, std::placeholders::_1, std::placeholders::_2));
    //5. 设置监听端口
    wssrv.listen(8085);
    //6. 开始获取新连接
    wssrv.start_accept();
    //7. 启动服务器
    wssrv.run();
    return 0;
}

(五)JsonCpp使用

Json数据格式
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]} 
]

Json 的数据类型包括对象,数组,字符串,数字等。
对象:使用花括号 {} 括起来的表示一个对象
• 数组:使用中括号 [] 括起来的表示一个数组
• 字符串:使用常规双引号 “” 括起来的表示一个字符串
• 数字:包括整形和浮点型,直接使用

Jsoncpp 库主要是用于实现 Json 格式数据的序列化和反序列化,它实现了将多个数据对象组织成为 json 格式字符串,以及将 Json 格式字符串解析得到多个数据对象的功能。先看⼀下 Json 数据对象类的表示:

1 class Json::Value {
2 Value &operator=(const Value &other); //Value重载了[]和=,因此所有的赋值和获取
数据都可以通过
3 Value& operator[](const std::string& key);//简单的⽅式完成 val["name"] = 
"xx";
4 Value& operator[](const char* key);
5 Value removeMember(const char* key);//移除元素
6 const Value& operator[](ArrayIndex index) const; //val["score"][0]
7 Value& append(const Value& value);//添加数组元素val["score"].append(88); 
8 ArrayIndex size() const;//获取数组元素个数 val["score"].size();
9 bool isNull(); //⽤于判断是否存在某个字段
10 std::string asString() const;//转string string name = 
val["name"].asString();
11 const char* asCString() const;//转char* char *name = 
val["name"].asCString();
12 Int asInt() const;//转int int age = val["age"].asInt();
13 float asFloat() const;//转float float weight = val["weight"].asFloat();
14 bool asBool() const;//转 bool bool ok = val["ok"].asBool();
15 
};

Jsoncpp 库主要借助三个类以及其对应的少量成员函数完成序列化及反序列化

  • 序列化接口
1 class JSON_API StreamWriter {
2 virtual int write(Value const& root, std::ostream* sout) = 0;
3 }
4 class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
5 virtual StreamWriter* newStreamWriter() const;
6 }
  • 反序列化接口
1 class JSON_API CharReader {
2 virtual bool parse(char const* beginDoc, char const* endDoc, 
3 Value* root, std::string* errs) = 0;
4 }
5 class JSON_API CharReaderBuilder : public CharReader::Factory {
6 virtual CharReader* newCharReader() const;
7 }
  • JsonCpp功能代码⽤例编写
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <jsoncpp/json/json.h>

//使用jsoncpp库进行多个数据对象的序列化
std::string serialize() {
    //1. 将需要进行序列化的数据,存储在Json::Value 对象中
    Json::Value root;
    root["姓名"] = "小明";
    root["年龄"] = 18;
    root["成绩"].append(98);
    root["成绩"].append(88.5);
    root["成绩"].append(78.5);
    //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 serialize failed!!\n";
        return "";
    }
    std::cout << ss.str() << std::endl;
    delete sw;
    return ss.str();
}

void unserialize(const std::string &str)
{
    //1. 实例化一个CharReaderBuilder工厂类对象
    Json::CharReaderBuilder crb;
    //2. 使用CharReaderBuilder工厂类生产一个CharReader对象
    Json::CharReader *cr = crb.newCharReader();
    //3. 定义一个Json::Value对象存储解析后的数据
    Json::Value root;
    std::string err;
    //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, &err);
    if (ret == false) {
        std::cout << "json unserialize failed: " << err << std::endl;
        return ;
    }
    //5. 逐个元素去访问Json::Value中的数据
    std::cout << "姓名:" << root["姓名"].asString()  << std::endl;
    std::cout << "年龄:" << root["年龄"].asInt()  << std::endl;
    int sz = root["成绩"].size();
    for (int i = 0; i < sz; i++) {
        std::cout << "成绩: " << root["成绩"][i].asFloat() << std::endl;
    }
    delete cr;
}
int main()
{
    std::string str = serialize();
    unserialize(str);
    return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1118750.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue基础与常用指令,Element基础

1.vue快速入门 vue概述 Vue是一套构建用户界面的渐进式前端框架 只关注视图层&#xff0c;并且非常容易学习&#xff0c;还可以很方便的与其它库或已有项目整合 通过尽可能简单的API来实现响应数据的绑定和组合的视图组件 特点 易用&#xff1a;在有HTMLCSSJavaScript的基…

http post协议发送本地压缩数据到服务器

1.客户端程序 import requests import os # 指定服务器的URL url "http://192.168.1.9:8000/upload"# 压缩包文件路径 folder_name "upload" file_name "test.7z" headers {Folder-Name: folder_name,File-Name: file_name } # 发送POST请求…

ExelaStealer:新型低成本网络犯罪武器崭露头角

网络犯罪的工具层出不穷&#xff0c;而最新的一款信息窃取器ExelaStealer也开始崭露头角。这种低成本的恶意软件专门针对受损的Windows系统&#xff0c;用于窃取敏感数据。据Fortinet FortiGuard Labs研究员James Slaughter在一份技术报告中表示&#xff1a;“ExelaStealer是一…

Arcgis 数据操作

在进行数据操作的时候&#xff0c;需要注意坐标系要一致&#xff0c;这是前提。 数据类型 文件地理数据库&#xff1a;gbd 个人地理数据库&#xff1a;mdb &#xff08;Mircosoft Access&#xff09; 矢量数据&#xff1a;shp 推荐使用gbd数据&#xff0c;效率会更高。 采…

C/C++程序设计和预处理

个人主页&#xff1a;仍有未知等待探索_C语言疑难,数据结构,小项目-CSDN博客 专题分栏&#xff1a;C语言疑难_仍有未知等待探索的博客-CSDN博客 目录 一、引言 二、程序的翻译环境和执行环境 1、什么是程序 2、程序的翻译环境 3、程序的执行环境 三、预处理 1、预定义符…

排序算法,冒泡排序算法及优化,选择排序SelectionSort,快速排序(递归-分区)

一、冒泡排序算法&#xff1a; 介绍&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单直观的排序算法。它重复地走访过要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需…

Nginx虚拟主机的搭建 基于ip 基于端口 基于域名

一、虚拟主机介绍 虚拟主机是一种特殊的软硬件技术&#xff0c;他可以将网络上的每一台计算机分成多个虚拟主机&#xff0c;每个虚拟主机可以单独对外提供web服务&#xff0c;这样就可以实现一台主机对多个web服务&#xff0c;每个虚拟主机都是独立的&#xff0c;互相不影响 ng…

卫星业务。。。。

卫星业务 • 卫星运营围绕三个主要部分展开 &#xff1a; – 运营卫星业务的 地面段 – 由所有空间资产组成的 空间段 – 接收卫星服务&#xff08;如 GPS 或通信&#xff09;的 用户段 • 1. 地面段 – 在卫星的整个生命周期中&#xff0c;地面段是所有卫星运行的中心。 • 一…

【Javascript】对象中的常规操作(增删改查)

目录 创建对象&#xff0c;并在控制台里打印该对 增 改 删 查 创建对象&#xff0c;并在控制台里打印该对象 增 给person这个对象增加一个性别的属性 对象 . 属性值 改 例如将年龄改为20 删 例如删除性别 查 除了console.log(person.?)查询

Leetcode1838. 最高频元素的频数

Every day a Leetcode 题目来源&#xff1a;1838. 最高频元素的频数 解法1&#xff1a;排序 滑动窗口 发现1&#xff1a;操作后的最高频元素必定可以是数组中已有的某一个元素。 发现2&#xff1a;优先操作距离目标值最近的&#xff08;小于目标值的&#xff09;元素。 …

SpringBoot项目创建失败或无法启动,启动报错时的常见问题及解决方案

1、无法启动&#xff0c;没有启动的三角按钮 原因&#xff1a;idea没有将其识别为一个maven项目 解决方案&#xff1a;告诉idea&#xff0c;这是一个maven项目 1.1、如果右侧有Maven项目&#xff0c;刷新一下 1.2、左侧项目鼠标右键&#xff0c;添加Maven框架支持 若没有选择m…

Vue2基础知识(三) 组件化

目录 一 组件1.1 组件的定义1.2 特点1.3 Vue-extend1.4 VueCompent 二 脚手架2.1 安装2.2 结构目录2.3 Render函数2.4 修改默认配置2.5 Ref 属性2.6 Prop 属性2.7 Mixin 属性2.8 插件2.9 Scoped 三 组件3.1 组件的注册3.1.1 局部注册3.1.2 全局注册 3.2 组件的通信3.2.1 父子关…

差分时钟与DDR3

Zynq上的存储器接口 所有 Zynq-7000 AP芯片上的存储器接口单元包括一个动态存储器控制器和几个 静态存储器接口模块。动态存储器控制器可以用于 DDR3、DDR3L、DDR2 和 LPDDR2。 静态存储器控制器支持一个 NAND 闪存接口、一个 Quad-SPI 闪存接口、一个并行数 据总线和并行 NOR …

python中的yolov5结合PyQt5,使用QT designer设计界面没正确启动的解决方法

python中的yolov5结合PyQt5&#xff0c;使用QT designer设计界面没正确启动的解决方法 一、窗体设计test: 默认你已经设计好了窗体后&#xff1a; 这时你需要的是保存生成的untitle.ui到某个文件夹下&#xff0c;然后在命令行中奖.ui转换为.py&#xff08;&#xff0c;通过​​…

JAVA面经整理(MYSQL篇)

索引: 索引是帮助MYSQL高效获取数据的排好序的数据结构 1)假设现在进行查询数据&#xff0c;select * from user where userID89 2)没有索引是一行一行从MYSQL进行查询的&#xff0c;还有就是数据的记录都是存储在MYSQL磁盘上面的&#xff0c;比如说插入数据的时候是向磁盘上面…

web 安全总结

1、web安全总结 1.1 web安全简介 1.1.1 http协议 http 协议是超文本传输协议-明文传输 https 协议是http协议的基础上进行升级&#xff0c;是数据在传输过程中进行加密 1.1.2 http请求 http请求分为&#xff1a;请求方法、请求头、请求体 GET、PUT、POST、OPTIONS、move、…

Qt中Json的操作

在 Json的两种格式中介绍了Json的格式以及应用场景。由于这种数据格式与语言无关,下面介绍一下Json在Qt中的使用。 从Qt 5.0开始提供了对Json的支持,我们可以直接使用Qt提供的Json类进行数据的组织和解析。相关的类常用的主要有四个,具体如下: Json类介绍 QJsonDocument |…

Mac M1下使用Colima替代docker desktop搭建云原生环境

文章目录 为什么不使用docker desktop1.docker desktop卸载2.docker、docker compose安装3.colima安装3.1获取镜像地址3.2将下载好的iso文件放到colima指定路径3.3重新执行colima start 4.minikukekubernetes安装5.关闭minikube Mac M1下使用Colima替代docker desktop搭建云原生…

【数据分享】我国专精特新“小巨人”企业数据(excel格式\shp格式)

企业是经济活动的参与主体。一个城市的企业数量决定了这个城市的经济发展水平&#xff01;比如一个城市的金融企业较多&#xff0c;那这个城市的金融产业肯定比较发达&#xff1b;一个城市的制造业企业较多&#xff0c;那这个城市的制造业肯定比较发达。之前我们分享过2023年高…

使用WPF模仿Windows记事本界面

本次仅模仿Windows记事本的模样&#xff0c;并未实现其功能。 所有代码如下&#xff1a; <Window x:Class"控件的基础使用.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/…