政府网站建设报价/网站文章优化技巧

政府网站建设报价,网站文章优化技巧,wordpress4.6 手册,邢台网站建设免费做网站排名介绍HTTP协议基本结构与基本实现HTTPServer HTTP协议 前面已经了解了协议的重要性并且已经定义了属于我们自己的协议,但是在网络中,已经有一些成熟的协议,最常用的就是HTTP协议 在互联网世界中,HTTP(HyperText Tran…

介绍HTTP协议基本结构与基本实现HTTPServer

HTTP协议

前面已经了解了协议的重要性并且已经定义了属于我们自己的协议,但是在网络中,已经有一些成熟的协议,最常用的就是HTTP协议

在互联网世界中,HTTP(HyperText Transfer Protocol,超文本传输协议)是一个至关重要的协议。它定义了客户端(如浏览器)与服务器之间如何通信,以交换或传输超文本(如HTML文档)

HTTP协议是客户端与服务器之间通信的基础。客户端通过HTTP协议向服务器发送请求,服务器收到请求后处理并返回响应。HTTP协议是一个基于TCP协议的无连接、无状态的协议,即每次请求都需要建立新的连接,且服务器不会保存客户端的状态信息

因为HTTP是基于TCP的,而TCP是面向字节流的,所以在传递信息时肯定会存在收到的信息不完整的情况,那么根据前面的经验,不论是客户端和服务端都需要做数据完整性检查

URL与URI

URI(统一资源标识符)是用于标识网络资源的字符串,而URL(统一资源定位符)是URI的一个扩展,它不仅标识资源,还提供了定位该资源的方法

一个标准的URL通常包含以下几个部分:

http://www.example.com:80/path/to/resource?param1=value1&param2=value2#fragment
  1. 协议(http://):指定客户端和服务器之间通信使用的协议
  2. 主机名(www.example.com):资源所在服务器的域名或IP地址
  3. 端口号(:80):服务器上运行的服务的端口号(HTTP默认为80)
  4. 路径(/path/to/resource):资源在服务器上的具体位置
  5. 查询参数(?param1=value1&param2=value2): 发送给服务器的额外参数
  6. 片段标识符(#fragment): 资源内的特定部分的引用

深入URL结构

仔细观察URL的结构,除去协议、主机名和端口号以外,剩余的部分正好就是文件的路径,而在操作系统之下标记一个文件的路径也是使用同样的结构,所以这里就可以得出一个结论:URL的结构实际上就是找到对应的主机,再在该主机上找到指定路径下的文件

两台计算机进行网络通信实际上就是在做IO,而要做IO就需要有对应的数据交换,所以首先就必须要定位到文件的位置,定位文件就是通过路径进行的,所以URL的设计思想对应的就是操作系统定位文件的方式,但是需要注意在URL中,路径开始的第一个/并不代表着操作系统的根目录,而是Web应用的根目录

URL编码

URL编码是一种将非ASCII字符和特殊字符转换为可在URL中安全传输的编码方式。因为URL只能使用ASCII字符集中的一部分字符,所以需要对其他字符进行编码

编码原理

URL编码遵循以下规则:

  1. ASCII字母、数字和某些特殊字符保持不变,即:

    • 字母:A-Z, a-z
    • 数字:0-9
    • 特殊字符:-, _, ., ~
  2. 其他字符(如空格、中文、特殊符号)按照以下步骤编码:

    • 将字符转换为字节序列(通常使用UTF-8编码)
    • 每个字节用百分号%后跟两位十六进制数表示

常见编码示例

字符URL编码说明
空格%20 (或 +)空格可以编码为%20+(表单提交时)
!%21感叹号
#%23井号(必须编码,因为在URL中有特殊含义)
$%24美元符号
&%26和号(必须编码,因为用于分隔参数)
+%2B加号
/%2F正斜杠(在路径中通常不编码)
:%3A冒号(在协议分隔符后通常不编码)
=%3D等号(在查询参数中通常不编码)
?%3F问号(必须编码,因为用于引导查询参数)
@%40at符号
%E4%B8%AD汉字"中"的UTF-8编码

编码示例

原始URL中包含中文和特殊字符:

https://example.com/搜索?关键词=中国&category=历史

编码后的URL:

https://example.com/%E6%90%9C%E7%B4%A2?%E5%85%B3%E9%94%AE%E8%AF%8D=%E4%B8%AD%E5%9B%BD&category=%E5%8E%86%E5%8F%B2

URL编码的应用场景

  1. 查询参数传递:确保包含特殊字符的参数能正确传递
  2. 表单提交:当使用GET方法提交表单时,表单数据会编码到URL中
  3. 国际化URL:包含非英语字符的URL需要编码
  4. 防止字符注入攻击:编码可以防止某些特殊字符被解释为代码

注意事项

  • 不同的字符集可能产生不同的编码结果,现代Web应用通常使用UTF-8
  • 某些旧系统可能使用非标准编码(如GB2312)
  • 浏览器会自动对输入的URL进行编码
  • 在服务器端编程中,各种语言都提供了URL编码和解码的函数
  • 编码应该在正确的位置进行,不要对整个URL进行编码,而是对各部分中的特殊字符进行编码

URL编码确保了含有特殊字符的数据可以通过URL安全传输,是Web应用开发中的基础知识

HTTP请求结构和HTTP响应结构

基本认识

既然是传递数据,那么肯定要做的就是确定双方都认识的一个结构,这样获取到的数据才能被正确解释,在HTTP中,有两种结构,分别是HTTP请求和HTTP响应

一个基本的HTTP请求结构如下图所示:

在这里插入图片描述

一个基本的HTTP响应结构如下图所示:

在这里插入图片描述

在上面两个结构图中,可以看到都存在换行符,这里的换行符更准确来说应该是\r\n

但是这仅仅只是定义了结构,根据前面的知识可以知道除了有结构以外,还需要对结构化的数据进行序列化和反序列化,HTTP协议的设计者也考虑到了这一点,所以HTTP实际上有自己的序列化和反序列化方式,而不需要程序员自己去实现前面类似于使用JSONCPP库进行JSON格式字符串的来回转换

HTTP请求结构

在HTTP请求结构中:

首先是请求行部分,其中第一个就是HTTP的请求方法,具体的方法一共有6种,但是最常见的就是GETPOST方法,具体二者的区别会在后面的章节进行讲解;接着是URI实际上对应的就资源路径;最后就是HTTP版本,具体在HTTP版本部分会有具体介绍,此处不具体说明

第二部分就是请求报头,请求报头所有的属性都是以key: value的形式存在,具体存在哪些属性在后面的章节会提及,此处不具体说明

最后就是请求正文,这里一般存放着请求时传递给服务器的参数,但是具体是否存在请求参数需要看请求方式,具体见后面的章节进行讲解

HTTP响应结构

在HTTP响应结构中:

首先是响应行部分,第一个就是HTTP版本,之所以HTTP请求和响应中都需要指定版本号是为了确保通信双方能够正确理解和处理彼此的消息,处理版本差异,并在不同版本的HTTP协议间提供平滑的过渡。这种设计使得HTTP协议能够在保持向后兼容的同时不断发展和改进;接着是状态码,HTTP协议规定,不论是请求成功还是请求失败都需要给客户端响应,但是如果一味地响应同一种数据,那么客户端就无法分辨哪一个为正常数据,所以为了标识不同的响应结果,就需要这个状态码,在深入HTTP序列化和反序列化有具体讲解,此处不具体说明;最后就是状态码描述,这个描述文字对应的状态码的含义,具体见深入HTTP序列化和反序列化

第二部分和第三部分与HTTP请求结构的第二部分相同,此处不再赘述

封装网络接口

接下来需要编写处理HTTP请求的服务器,而因为HTTP是基于TCP的,所以为了后面编写的方便,此处先对前面使用的网络接口进行封装

基本设计思路

本次封装考虑采用模版方法设计模式(Template Method Pattern),其是一种行为型设计模式,它定义了一个算法的框架,但将一些步骤的具体实现延迟到子类中。通过这种方式,模板方法允许子类在不改变算法结构的情况下重新定义某些步骤

该模式的核心思想是:在父类中定义算法的整体结构,而将某些具体步骤留给子类去实现 。这样可以确保算法的骨架保持一致,同时允许子类根据需要自定义某些细节

在模版方法设计模式中存在一些核心概念:

  1. 抽象类(Abstract Class):定义了算法的整体框架,并包含一个或多个抽象方法(由子类实现)。此外,它还可能包含一些具体方法(默认实现),这些方法可以直接被子类复用
  2. 模板方法(Template Method):模板方法是一个具体方法,一般不允许被子类重写。它定义了算法的执行步骤,调用了抽象方法和具体方法
  3. 具体类(Concrete Class):具体类(子类)继承抽象类,并实现抽象方法,提供具体的实现逻辑

根据这个模式的基本介绍,下面考虑具体的设计思路:

首先是抽象类,定义为BaseSocket,其中提供一系列抽象方法和一个具体模版方法initSocket,在具体模版方法中需要调用抽象方法,当子类实现抽象方法后,通过向上转型调用抽象类中的具体方法

接着是具体类,具体类一共有两个,一个是UdpSocket,另外一个是TcpSocket,因为本次需要实现HttpServer,所以重点实现TcpSocket

在具体方法中,因为是针对TcpSocket,所以需要经过下面的三个步骤:

  1. 创建服务器监听套接字
  2. 绑定服务器监听套接字
  3. 服务器进入监听状态

根据这三个步骤,在initSocket函数中就需要对应的三个方法的调用

设计抽象类

根据上面的思路,可以设计出抽象类如下:

class BaseSocket
{
public:virtual ~BaseSocket() = default;// 创建套接字virtual void createSocket() = 0;// 绑定virtual void toBind() = 0;// 监听virtual void toListen() = 0;// 具体实现方法void initSocket(){createSocket();toBind();toListen();}
};

设计具体类

本次以TCP为例,设计TcpServer类,需要继承BaseServer并实现对应的抽象方法,需要注意,子类不允许实现initServer方法,实现方式与前面类似,只是将具体逻辑抽取到单独的函数中,代码如下:

// 默认端口
const uint16_t default_port = 8080;
// 默认最大支持排队等待连接的客户端个数
const int max_backlog = 8;class TcpSocket : public BaseSocket
{
public:TcpSocket(int port = default_port): _listen_socketfd(-1), _s_addr_in(port){}// 实现创建套接字void createSocket() override{_listen_socketfd = socket(AF_INET, SOCK_STREAM, 0);if (_listen_socketfd < 0){LOG(LogLevel::FATAL) << "监听套接字创建失败:" << strerror(errno);exit(static_cast<int>(ErrorNumber::SocketFail));}LOG(LogLevel::INFO) << "监听套接字创建成功:" << _listen_socketfd;}// 实现绑定void toBind() override{int n = bind(_listen_socketfd, &_s_addr_in, _s_addr_in.getLength());if (n < 0){LOG(LogLevel::ERROR) << "绑定失败:" << strerror(errno);exit(static_cast<int>(ErrorNumber::BindSocketFail));}LOG(LogLevel::INFO) << "绑定成功";}// 实现监听void toListen() override{int ret = listen(_listen_socketfd, max_backlog);if (ret < 0){LOG(LogLevel::ERROR) << "监听失败:" << strerror(errno);exit(static_cast<int>(ErrorNumber::ListenFail));}LOG(LogLevel::INFO) << "监听成功";}~TcpSocket(){}private:int _listen_socketfd;  // 监听套接字SockAddrIn _s_addr_in; // 套接字结构
};

接着,因为TCP还需要一个接收过程,所以还需要一个接口用于接收,并且为了让上层处理具体的客户端信息,考虑将客户端信息返回给上层

根据这个思路,首先在抽象类中定义接收抽象函数和获取接收套接字函数:

// 接收
virtual SockAddrIn toAccept() = 0;

接着在具体类中实现:

// 实现接收
SockAddrIn toAccept() override
{struct sockaddr_in peer;socklen_t length = sizeof(peer);int ac_socketfd = accept(_listen_socketfd, reinterpret_cast<struct sockaddr *>(&peer), &length);if(ac_socketfd < 0){LOG(LogLevel::ERROR) << "接收失败:" << strerror(errno);exit(static_cast<int>(ErrorNumber::AcceptFail));}LOG(LogLevel::INFO) << "接收成功:";// 向上层返回客户端return peer;
}

实现TcpServer

有了基本接口的封装后,因为HttpServer基于TCP,所以需要先实现TcpServer类,基本思路如下:

对于TcpServer类来说,需要考虑的事情就是执行任务,而因为是服务器,本次考虑只让服务器做监听和接收而不进行任何其他任务,所以考虑使用回调函数将任务交给上层。但是现在就遇到了一个问题,TcpSocketac_socketfd是一个局部变量,并且此时没有相应的接口可以获得该局部变量,所以为了解决这个问题,可以考虑对开始的toAccept函数进行改写

首先,为了外部可以获取到客户端的信息,可以考虑设计一个输出型参数:

void toAccept(SockAddrIn *client)
{// ...
}

接着,为了外部可以直接使用接收成功后的套接字,这里直接将函数返回值修改为int即可:

int toAccept(SockAddrIn *client)
{// ...
}

最后,整体修改toAccept函数的逻辑:

// 实现接收
int toAccept(SockAddrIn* client) override
{struct sockaddr_in peer;socklen_t length = sizeof(peer);int ac_socketfd = accept(_listen_socketfd, reinterpret_cast<struct sockaddr *>(&peer), &length);if (ac_socketfd < 0){LOG(LogLevel::ERROR) << "接收失败:" << strerror(errno);exit(static_cast<int>(ErrorNumber::AcceptFail));}LOG(LogLevel::INFO) << "接收成功:";*client = peer;// 向上层返回客户端return ac_socketfd;
}

既然服务器要做监听和接收,那么少不了的就是调用TcpSocket中的监听和接收接口,而因为监听是在初始化就开始了,所以只需要在启动时处理接收即可,接着将其他任务交给上层,但是,交给上层之前,需要处理好接收和任务分离,保证接收和执行任务可以独立进行,此时就需要利用前面的线程或者进程,本次考虑使用线程,所以基本代码如下:

using task_t = std::function<void(SockAddrIn, int)>;
using base_socket_ptr = std::shared_ptr<BaseSocket>;class TcpServer;struct data
{SockAddrIn client;int ac_socketfd;TcpServer* self;
};class TcpServer
{
public:TcpServer(uint16_t port = default_port):_bs(std::make_shared<TcpSocket>(port)),_isRunning(false){_bs->initSocket();}// 注册方法void registerFunc(task_t handler){_handler = handler;}static void* routine(void* args){struct data* ptr = reinterpret_cast<struct data*>(args);ptr->self->_handler(ptr->client, ptr->ac_socketfd);return NULL;}void start(){_isRunning = true;while (_isRunning){SockAddrIn client;// 因为在SockAddrIn内部重载了&,此处注意使用addressof取出当前对象的实际地址int ac_socketfd = _bs->toAccept(std::addressof(client));pthread_t pid;struct data d = {client, ac_socketfd, this};pthread_create(&pid, NULL, routine, &d);}}// 获取底层接口base_socket_ptr getSocketPtr(){return _bs;}private:std::shared_ptr<BaseSocket> _bs; // 向上转型bool _isRunning;task_t _handler;
};

实现HTTP服务器

有了基本的TcpServer类后就可以开始实现基于TCP的HTTP服务器,为了能够快速看到服务器运行效果,先搭建一个基本的服务器端。这个服务器需要实现的功能:当浏览器请求服务端时可以看到服务端给浏览器回显的一行HTML内容

有了目标功能后,现在考虑如何实现这个功能。既然要给浏览器回显一行HTML内容,那么服务器就必须要有给客户端返回HTTP响应的功能。需要注意,本次客户端只是发送一个不含有任何请求报头和请求体的HTTP请求,所以服务器可以不用对客户端的请求进行细致化处理,具体如何细致化处理会在深入HTTP序列化和反序列化

创建HttpServer

因为HTTP是基于TCP的,所以在HttpServer类中需要有一个TcpServer成员,接着根据前面的思路,需要提供处理HTTP请求的函数,所以整体结构如下:

class HttpServer
{
public:HttpServer(uint16_t port = default_port):_tp(std::make_shared<TcpServer>(port)){}void handleHttpRequest(SockAddrIn sock_addr_in, int ac_socketfd){}private:std::shared_ptr<TcpServer> _tp;
};

但是,上面的基本结构中还缺少一个关键的环节:启动服务器。启动HTTP服务器本质就是启动TcpServer,启动TcpServer时需要传递执行的任务,因为本次TcpServer执行的就是处理HTTP请求,所以执行的函数就是handleHttpRequest,所以实现如下:

void start()
{// 注册方法_tp->registerFunc([this](SockAddrIn sock_addr_in, int ac_socketfd){this->handleHttpRequest(sock_addr_in, ac_socketfd);});_tp->start();
}

实现处理HTTP请求接口

根据前面提到的目标,服务器只需要根据HTTP响应结构向客户端返回对应的内容即可。首先,构建一个内容作为HTTP响应结构的响应体:

std::string msg = "<h1>Hello Linux</h1>";
const std::string sep = "\r\n";
std::string body = msg + sep;
std::string status_line = "HTTP/1.1 200 OK" + sep + sep;std::string httpResponse = status_line + body;

接着要实现发送,就必须要调用对应的接口,即send,所以基本实现如下:

void handleHttpRequest(SockAddrIn sock_addr_in, int ac_socketfd)
{LOG(LogLevel::INFO) << "收到来自:" << sock_addr_in.getIp() << ":" << sock_addr_in.getPort() << "的连接";// 不对客户端发送的HTTP请求进行处理// 向客户端发送一个HTTP响应std::string msg = "<h1>Hello Linux</h1>";const std::string sep = "\r\n";std::string body = msg + sep;std::string status_line = "HTTP/1.1 200 OK" + sep + sep;std::string httpResponse = status_line + body;ssize_t ret = send(ac_socketfd, httpResponse.c_str(), httpResponse.size(), 0);(void)ret;
}

测试

测试代码如下:

#include "HttpServer.hpp"
#include <memory>using namespace HttpServerModule;int main(int argc, char* argv[])
{uint16_t port = std::stoi(argv[1]);std::shared_ptr<HttpServer> hs = std::make_shared<HttpServer>(port);hs->start();return 0;
}

编译运行后打开浏览器输入对应的IP地址和端口号即可看到一个客户端收到的内容:

在这里插入图片描述

封装发送和接收接口

在上面最后一步:向客户端发送HTTP响应时使用的是底层send接口,既然是底层接口,同样可以考虑对这个接口进行封装,同时也对接收接口进行封装。因此,封装的基本思路为:首先在BaseSocket基类中创建接口和发送两个接口的声明,再在具体实现类TcpSocket中实现这两个接口:

=== “BaseSocket

// 发送数据
virtual void sendData(std::string &in_data, int ac_socketfd) = 0;
// 接收数据
virtual void recvData(std::string &out_data, int ac_socketfd) = 0;

=== “TcpSocket

 // 接收数据void recvData(std::string &out_data, int ac_socketfd) override{char buffer[4096] = {0};ssize_t ret = recv(ac_socketfd, buffer, sizeof(buffer), 0);if(ret > 0){out_data = buffer;}}// 发送数据void sendData(std::string &in_data, int ac_socketfd) override{ssize_t ret = send(ac_socketfd, in_data.c_str(), in_data.size(), 0);(void)ret;}

但是,现在又遇到了第二个问题,因为接收数据接口和发送数据接口都是TcpSocket类中的,而在HttpServer中是TcpServer,无法直接调用到TcpSocket中的接收和发送接口,这里最直接的思路就是在TcpServer中提供一个接口返回底层的TcpSocket类或者其基类对象:

socket_ptr getSocketPtr()
{return _bs;
}

此时在上层就可以调用该接口获取到调用对象的指针,对应的整体处理HTTP请求接口实现如下:

void handleHttpRequest(SockAddrIn sock_addr_in, int ac_socketfd)
{LOG(LogLevel::INFO) << "收到来自:" << sock_addr_in.getIp() << ":" << sock_addr_in.getPort() << "的连接";// 不对客户端发送的HTTP请求进行处理// 向客户端发送一个HTTP响应// ...std::shared_ptr<BaseSocket> bs = _tp->getSocketPtr();bs->sendData(httpResponse, ac_socketfd);
}

再次编译运行后打开浏览器输入对应的IP地址和端口号即可看到一个客户端收到的内容:
在这里插入图片描述

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

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

相关文章

Git使用和原理(3)

1.远程操作 1.1分布式版本控制系统 我们⽬前所说的所有内容&#xff08;⼯作区&#xff0c;暂存区&#xff0c;版本库等等&#xff09;&#xff0c;都是在本地&#xff01;也就是在你的笔记本或者 计算机上。⽽我们的 Git 其实是分布式版本控制系统&#xff01;什么意思呢&a…

c语言zixue

该文主要是记录我学习中遇到的一些重点、易出问题的内容 教材p16.17 先从一个简单的例子开始吧 #include <stdio.h> //编译预处理命令 int main() //程序的主函数 {printf("To C"); //输出语句return 0; //返回语句 } #include <stdio.h>是编译预…

【开源代码解读】AI检索系统R1-Searcher通过强化学习RL激励大模型LLM的搜索能力

关于R1-Searcher的报告&#xff1a; 第一章&#xff1a;引言 - AI检索系统的技术演进与R1-Searcher的创新定位 1.1 信息检索技术的范式转移 在数字化时代爆发式增长的数据洪流中&#xff0c;信息检索系统正经历从传统关键词匹配到语义理解驱动的根本性变革。根据IDC的统计…

从0到1入门Docker

一、快速入门 Docker run命令中的常见参数 -d&#xff1a;让容器后台运行--name&#xff1a;给容器命名&#xff08;唯一&#xff09;-e&#xff1a;环境变量-p&#xff1a;宿主机端口映射到容器内端口镜像名称结构&#xff1a;Repository &#xff1a;TAG&#xff08;镜像名&…

接口自动化入门 —— Jmeter实现在接口工具中关联接口处理方案

1. JMeter 接口关联处理的核心概念 接口关联是指在多个接口请求之间共享数据&#xff0c;例如将一个接口的返回值作为另一个接口的输入参数。常见的场景包括&#xff1a; 使用登录接口返回的 Token 作为后续接口的认证信息。 将一个接口返回的 ID 作为另一个接口的请求参数。…

Flink-学习路线

最近想学习一下Flink&#xff0c;公司的实时需求还是不少的&#xff0c;因此结合ai整理了一份学习路线&#xff0c;记录一下。 当然&#xff0c;公司也有Scala版本Flink框架&#xff0c;也学习了一下。这里只说Java版本 1. Java基础 目标: 掌握Java编程语言的基础知识。 内容…

ranger集成starrock报错

org.apache.ranger.plugin.client.HadoopException: initConnection: Unable to connect to StarRocks instance, please provide valid value of field : {jdbc.driverClassName}.. com.mysql.cj.jdbc.Driver. 可能的原因 JDBC 驱动缺失&#xff1a;运行环境中没有安装 MySQL …

Blender-MCP服务源码2-依赖分析

Blender-MCP服务源码2-依赖分析 有个大佬做了一个Blender-MCP源码&#xff0c;第一次提交代码是【2025年3月7号】今天是【2025年月15日】也就是刚过去一周的时间&#xff0c;所以想从0开始学习这个代码&#xff0c;了解一下大佬们的开发思路 1-核心知识点 from mcp.server.fas…

反射(第三篇)、代理模式、静态代理和动态代理、InvocationHandler实际应用

DAY11.3 Java核心基础 反射&#xff08;第三篇&#xff09; 前两篇我们学习了反射的概念和基本操作 实际开发中&#xff0c;反射应用于那里&#xff1f; 动态代理 java中的动态代理就是一个重要的作用 代理模式 代理模式是java中常用的设计模式 指的是在处理一个业务逻辑…

数学建模 第一节

目录​​​​​​ 前言 一 优化模型的类型 二 线性规划1 线性规划2 三 0-1规划 总结 前言 数学建模主要是将问题转化为模型&#xff0c;然后再以编程的形式输出出来 算法都知道&#xff0c;数学建模也需要用到算法&#xff0c;但是不是主要以编程形式展示&#xff0c;而是…

网络空间安全(32)Kali MSF基本介绍

前言 Metasploit Framework&#xff08;简称MSF&#xff09;是一款功能强大的开源安全漏洞检测工具&#xff0c;被广泛应用于渗透测试中。它内置了数千个已知的软件漏洞&#xff0c;并持续更新以应对新兴的安全威胁。MSF不仅限于漏洞利用&#xff0c;还包括信息收集、漏洞探测和…

目标在哪里?——寻找人生的意义与方向

在职场中&#xff0c;许多人都会经历这样的困惑&#xff1a;工作看似顺利&#xff0c;却逐渐失去了成就感和成长感。一位在500强企业工作的学员就遇到了这样的问题。她曾考虑过转型做培训&#xff0c;但苦于找不到明确的切入点&#xff0c;对未来的目标感到迷茫。她不禁问自己&…

C++类与对象——拷贝构造与运算符重载

拷贝构造函数和赋值运算符重载就是C类默认六个函数之二。 拷贝构造函数&#xff1a; 如果⼀个构造函数的第⼀个参数是自身类类型的引用&#xff0c;且任何额外的参数都有默认值&#xff0c;则此构造函数 也叫做拷贝构造函数&#xff0c;也就是说拷贝构造是⼀个特殊的构造函数…

Linux:进程程序替换

目录 前言 一 进程程序替换的概念 二 进程程序替换的原理 三 为什么需要进行进程程序替换 四 如何进行进程程序替换 1. 进程替换函数 ➊ execl()函数 ➋execv()函数 ➌execlp()函数 ➍execle()函数 ➎execve()* 前言 一般情况下&#xff0c;对应的语言写的程序只…

Umi-OCR 全家桶

介绍&#xff1a; 下载 访问官网地址 https://github.com/hiroi-sora/umi-ocrhttps://github.com/hiroi-sora/umi-ocr 点击下载&#xff08;.exe 文件 安装即可&#xff09; 桌面使用 安装完毕后去安装路径下点击 Umi-OCR.exe &#xff08;默认不会生成桌面的快捷方式&…

2023南京理工大学计算机复试上机真题

2023南京理工大学计算机复试上机真题 2023南京理工大学计算机复试机试真题 历年南京理工大学计算机复试上机真题 在线评测&#xff1a;传送门&#xff1a;pgcode.cn 括号匹配二 题目描述 苗苗今天刚刚学会使用括号&#xff0c;不过他分不清小括号&#xff0c;中括号&#…

Axios简单说明,快速上手

Ajax&#xff1a;异步的JavaScript和XML 作用&#xff1a; 数据交换异步交互 Axios&#xff1a;就是对原生Ajax进行封装&#xff0c;简化书写&#xff0c;快速开发 使用逻辑&#xff1a; 首先要安装Axios&#xff0c;可以通过npm在项目中安装&#xff1a; 打开命令行工具…

模型评估——acc、P、R、F值、交叉验证、K折交叉验证

模型评估&#xff1a;对预测函数地预测精度的评估。 多重回归&#xff1a;涉及三个及其以上的变量的回归问题。 评估模型的方法&#xff1a; 交叉验证&#xff1a;将数据集分成测试集和训练集&#xff0c;可以采用3&#xff1a;7或者2&#xff1a;8的比例方式进行划分&#xff…

JVM 2015/3/15

定义&#xff1a;Java Virtual Machine -java程序的运行环境&#xff08;java二进制字节码的运行环境&#xff09; 好处&#xff1a; 一次编写&#xff0c;到处运行 自动内存管理&#xff0c;垃圾回收 数组下标越界检测 多态 比较&#xff1a;jvm/jre/jdk 常见的JVM&…

Compose 实践与探索九 —— DrawModifier 解析

本篇讲解 DrawModifier 的基本用法与代码原理&#xff0c;介绍原理的目的在于可以判断绘制与绘制的关系&#xff0c;绘制与布局的关系。知道达成某种绘制效果应该怎么写&#xff0c;面对复杂的 Modifier 链时对效果有大致预判。 DrawModifier 管理绘制&#xff0c;需要以负责管…