深圳市网站建设哪家好/java培训学费多少钱

深圳市网站建设哪家好,java培训学费多少钱,关于旅游网站开发的研究方法,网站页面太多怎么做网站地图目录 引言 一、WSAEventSelect模型概述 二、 WSAEventSelect模型的实现流程 2.1 创建一个事件对象,注册网络事件 2.2 等待网络事件发生 2.3 获取网络事件 2.4 手动设置信号量和释放资源 三、 WSAEventSelect模型伪代码示例 四、完整实践示例代码 引言 在网…

目录

引言

一、WSAEventSelect模型概述 

二、 WSAEventSelect模型的实现流程

2.1 创建一个事件对象,注册网络事件

2.2 等待网络事件发生

2.3 获取网络事件

2.4 手动设置信号量和释放资源

三、 WSAEventSelect模型伪代码示例

四、完整实践示例代码


引言

        在网络编程的复杂世界里,如何高效捕捉和响应网络事件是构建稳健应用的关键。WSAEventSelect模型作为一种强大的异步I/O模型,为开发者开辟了一条独特路径。它借助事件驱动机制,让应用程序能够敏锐感知套接字上的网络动态。与WSAAsyncSelect模型不同,它以事件而非消息形式传递通知,为网络编程带来别样灵活性。接下来,让我们深入探索WSAEventSelect模型的工作原理、实现流程以及实际应用示例。

一、WSAEventSelect模型概述 

        Windows Sockets异步事件选择模型,也就是WSAEventSelect模型,属于另一种异步I/O模型。利用这个模型,应用程序能够在单个或多个套接字上,基于事件接收网络方面的通知。

        WSAEventSelect模型和WSAAsyncSelect模型有所不同,主要区别就在于应用程序接收网络事件通知的方式。WSAEventSelect模型通过事件来告诉应用程序网络事件发生了,而WSAAsyncSelect模型是依靠消息来通知。但从根本上来说,在应用程序接收网络事件通知这件事上,这两个模型都是被动的。意思就是,只有网络事件真正发生的时候,系统才会向应用程序发出通知 。 

二、 WSAEventSelect模型的实现流程

初始化套接字、绑定端口及IP、监听这前三步在此略过。

2.1 创建一个事件对象,注册网络事件

        在应用程序调用WSAEventSelect函数之前,必须先创建一个事件对象。当获取到一个socket后,需使用WSACreateEvent函数来创建事件对象,之后再使用WSAEventSelect函数进行相关操作。

WSAEVENT WSACreateEvent(void);

该函数的返回值为事件对象句柄。

int WSAEventSelect(SOCKET s,             //当前服务端的SOCK句柄WSAEVENT hEventObject, //事件对象句柄long lNetworkEvents   //网络事件
);

         注:当调用WSAEventSelect函数后,套接字会被自动设置为非阻塞模式。若要将套接字设置为阻塞模式,则必须把参数lNetworkEvents设置为0。


示例:

//创建一个事件对象
WSAEVENT wsaEvent = WSACreateEvent();
if (WSA_INVALID_EVENT == wsaEvent) {printf("创建一个事件对象失败!");closesocket(sSocket);WSACleanup();
}
//注册网络事件
if (WSAEventSelect(sSocket,  wsaEvent,  //当前服务端的SOCK句柄//事件对象句柄FD_ACCEPT | FD_CLOSE)) {    //网络事件printf("注册网络事件失败!");closesocket(sSocket);   //关闭套接字WSACleanup();//释放套接字资源return FALSE;
}

2.2 等待网络事件发生

        在WinSockets应用程序里,先用WSAEventSelect函数给套接字把网络事件注册好,紧接着就得调用WSAWaitForMultipleEvents函数,目的是等着网络事件发生。这个WSAWaitForMultipleEvents函数的作用就是,一直等到有一个事件对象或者所有事件对象进入“有信号量”状态,又或者是函数调用时间到了(超时),它才会返回结果 。 

DWORD WSAWaitForMultipleEvents(DWORD cEvents,           //事件对象句柄数量WSAEVENT FAR*lphEvents, //指向事件对象句柄的指针BOOL fWaitAll,           //等待事件句柄的数量DWORD dwTimeout,         //调用该函数的阻塞时间BOOL fAlertable          //完成例程后是否继续等待
);

        WSAWaitForMultipleEvents这个函数,最多能够处理64个对象。所以呢,基于这个情况,使用这个I/O模型的时候,在一个线程里,同一时刻最多也就只能支持64个套接字。要是你想用这个模型去管理超过64个套接字,那就得再创建一些额外的工作线程才行。 

        WSAWaitForMultipleEvents函数的作用就是等着网络事件发生。只要在规定的时间里,有网络事件出现了,那这个函数返回的值,就能告诉你是哪个事件对象导致函数返回的 。 

        注:要是fWaitAll这个参数设成true,那所有的事件对象都会被置为有信号量状态。要是fWaitAll被设成FALSE,那么只要众多事件句柄当中有一个变为有信号量状态就可以了。这个函数运行结束后会给出一个返回值,这个返回值其实是个索引。用这个索引减去WSA_WAIT_EVENT_0这个宏的值,就能够知道在事件数组里,哪个事件被触发了,也就是能找到被触发事件在数组中的位置 。 


示例:

//定义事件对象数组
EventArray[WSA_MAXIMUMWAIT_EVENTS] = {};
//等待网络事件的发生
DWORD dwIndex =
WSAWaitForMultipleEvents(uEventCount, EventArray,  FALSE,
WSA_INFINITE,
FALSE);        
//完成例程后是否继续等待
//返回该事件在EventArray数组中的位置(下标从0开始)
dwIndex = dwIndex - WSA_WAIT_EVENT_0;

2.3 获取网络事件

        利用WSAWaitForMultipleEvents函数的返回值,我们能知道哪个套接字发生了网络事件。不过,仅仅知道是哪个套接字还不够,应用程序还得弄清楚在这个套接字上具体发生了哪种网络事件。WSAEnumNetworkEvents函数就派上用场了,它能找出套接字上发生的网络事件,同时把系统里关于这个网络事件的记录清除掉,还会把事件对象重新设置回初始状态 。

int WSAEnumNetworkEvents(SOCKET s,                          //发生网络事件的套接字句柄WSAEVENT hEventObject,             //被重置的事件对象句柄LPWSANETWORKEVENTS lpNetworkEvents //网络事件的记录和相应错误码
);
typedef struct _WSANETWORKEVENTS {long lNetworkEvents;               //网络事件int iErrorCode[FD_MAX_EVENTS];     //错误码
}

WSAEnumNetworkEvents参数

 _WSANETWORKEVENTS 参数

         使用方式:当lNetworkEvents&FD_XX为TRUE时,即表示发生了此网络事件。


示例:

Socket SocketArray[WSA_MAXIMUM_WAIT_EVENTS] = {};
int uEventCount = 0;                   //记录当前事件和套接字的个数
WSAEnumNetworkEvents(SocketArray[dwIndex],//发生网络事件的套接字句柄
EventArray[dwIndex],//被重置的事件对象句柄
&NetworkEvents))     //网络事件的记录和相应错误码
//响应网络事件
if ((NetworkEvents.lNetworkEvents & FD_ACCEPT) &&0 == NetworkEvents.iErrorCode[FD_ACCEPT_BIT]) {// 处理逻辑
}

        这个函数创建的事件对象,有“手动重设”和“自动重设”这两种工作模式。咱们这里创建的事件对象,是按手动方式工作的,一开始它处于无信号状态。一旦网络事件发生,跟套接字相关联的这个事件对象,就会从无信号量的状态变成有信号量状态。因为是“手动重设”模式,所以应用程序把相关事件处理完之后,得把这个有信号量的事件对象,再变回无信号量状态。 有个MAX_NUM_SOCKET宏,它的值是64 ,一般来说,这代表一个线程最多能同时等待处理64个事件,也就是说一个线程最多只能同时盯着64个socket。要是超过了这个数量,就必须再开启新的线程来处理。 调用这个函数的时候,如果hEventObject参数不是NULL,那么这个事件对象就会被自动重置为“无信号”状态;要是hEventObject参数是NULL,那就得调用WSAResetEvent函数,把事件设置成“无信号”状态 。 

2.4 手动设置信号量和释放资源

BOOL WSAResetEvent(WSAEVENT hEvent //要设置为无信号量的事件对象句柄
);


WSAResetEvent函数用于将事件对象从“有信号量”设置为“无信号量”。

BOOL WSACloseEvent(WSAEVENT hEvent //要释放资源的事件对象句柄
);

        应用程序完成网络事件的处理后,需要使用WSACloseEvent函数释放事件对象所占用的系统资源。

三、 WSAEventSelect模型伪代码示例

#include <Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
typedef struct _EVENT_SOCKET_INFO {WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];SOCKET SocketArray[WSA_MAXIMUM_WAIT_EVENTS];
}EVENT_SOCKET_INFO, *PEVENT_SOCKET_INFO;
BOOL SetSocket() {//1.初始化套接字WSADATA  stcData;int nResult;nResult = WSAStartup(MAKEWORD(2, 2), &stcData);if (nResult == SOCKET_ERROR)return FALSE;//2.创建套接字// 此处代码省略//3.初始化地址定址sockaddr_in sAddr = {0};sAddr.sin_family = AF_INET;sAddr.sin_port = htons(1234);sAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");int nSaddrLen = sizeof(sockaddr_in);//4.绑定int nRet = 0;nRet = bind(sSocket,(sockaddr*)&sAddr,sizeof  (sockaddr_in));if (SOCKET_ERROR == nRet) {printf("绑定IP定址失败");closesocket(sSocket);WSACleanup();}//接收返回信息//当前客户端SOCK句柄//IP定址//IP定址结构体大小//关闭套接字//释放套接字资源//WSANETWORKEVENTS NetworkEvents = {0};//网络事件的记录和相应错误码SOCKET                            sClientSocket           = 0;  //当前发送事件客户端的SOCK句柄UINT                                 uEventCount           = 0;  //事件对象句柄数量CLIENTINFO                  ClientInfo              = {0};//当前发送事件的客户端EVENT_SOCKET_INFO       EventSocketInfo = {0};//保存事件和Sock信息//5.监听if (listen(sSocket, SOMAXCONN)) {printf("    监听失败!");closesocket(sSocket);WSACleanup();}//6.创建一个事件对象WSAEVENT wsaEvent = WSACreateEvent();if (WSA_INVALID_EVENT == wsaEvent) {printf("创建一个事件对象失败!");closesocket(sSocket);WSACleanup();}//关闭套接字//释放套接字资源//7.注册网络事件if (WSAEventSelect(sSocket,wsaEvent,//当前服务端的SOCK句柄//事件对象句柄FD_ACCEPT | FD_CLOSE))//网络事件{printf("注册网络事件失败!");closesocket(sSocket);WSACleanup();//关闭套接字//释放套接字资源return FALSE;}//保存事件对象和套接字EventSocketInfo.EventArray[uEventCount]      = wsaEvent;EventSocketInfo.SocketArray[uEventCount++] = sSocket;while (TRUE) {WSAEVENT       EventArray[WSA_MAXIMUM_WAIT_EVENTS];//8.等待网络事件的发生DWORD dwIndex = WSAWaitForMultipleEvents(uEventCount,EventSocketInfo.EventArray,FALSE,WSA_INFINITE,FALSE);if (WSA_WAIT_FAILED == dwIndex)continue;//手动设置无信号//WSAResetEvent(EventSocketInfo.EventArray);//9.找到有信号的对象的标号//WSAWaitForMultipleEvent       函数的返回值-WSA_WAIT_EVENT_0dwIndex    = dwIndex - WSA_WAIT_EVENT_0;if (WSAEnumNetworkEvents(EventSocketInfo.SocketArray[dwIndex],//               发生网络事件的套接字句柄EventSocketInfo.EventArray                 [dwIndex],//被重置的事件对象句柄&NetworkEvents))                                               //网络事件的记录和相应错误码{printf("     调用WSAEnumNetworkEvents失败!");closesocket(sSocket);                                      //关闭套接字WSACleanup();                                                         //释放套接字资源}//10.响应网络事件//10.1连接if ((NetworkEvents.lNetworkEvents & FD_ACCEPT) &&0 == NetworkEvents.iErrorCode[FD_ACCEPT_BIT]) {sClientSocket       = accept(sSocket, (sockaddr*)&sAddr, &nSaddrLen);if (INVALID_SOCKET        == sClientSocket) {printf("     连接客户端失败!");continue;}//为新客户端创建网络事件//1.为刚连接进来的客户端创建事件对象EventSocketInfo.EventArray[uEventCount] = WSACreateEvent();//2.保存当前连接进来的客户端Socket 套接字EventSocketInfo.SocketArray[uEventCount] = sClientSocket;//3.为该客户端注册网络事件WSAEventSelect(sClientSocket,EventSocketInfo.EventArray[uEventCount],FD_READ | FD_WRITE                    | FD_CLOSE);uEventCount++;ClientInfo.ClientSock                  = sClientSocket;g_ClientInfo.push_back(ClientInfo);continue;}//10.2接收消息if ((NetworkEvents.lNetworkEvents & FD_READ) &&0        == NetworkEvents.iErrorCode[FD_READ_BIT]) {// 接收数据处理逻辑continue;}//10.3关闭事件if ((NetworkEvents.lNetworkEvents & FD_CLOSE) &&(0 == NetworkEvents.iErrorCode[FD   CLOSE_BIT])) {//关闭Socket套接字和释放事件对象占有的资源closesocket(EventSocketInfo.SocketArray[dwIndex]);WSACloseEvent(EventSocketInfo.EventArray[dwIndex]);//将退出的客户端从事件数组中删除,并将之后的数据向前移动for (int i = dwIndex; i < uEventCount; i++) {  //线性表EventSocketInfo.EventArray[dwIndex]= EventSocketInfo.EventArray[dwIndex + 1];EventSocketInfo.SocketArray[dwIndex]= EventSocketInfo.SocketArray[dwIndex + 1];}uEventCount--;continue;}}return TRUE;
}

        WSAEventSelect模型作为一种异步I/O模型,通过事件机制实现网络事件的通知与处理,在网络编程中为应用程序提供了一种有效的处理网络操作的方式,了解其原理和实现流程有助于开发者编写出更高效、稳定的网络应用程序。

四、完整实践示例代码

头文件initsock.h:

#include <winsock2.h>
#pragma comment(lib, "WS2_32")  // 链接到 WS2_32.libclass CInitSock
{
public:/*CInitSock 的构造器*/CInitSock(BYTE minorVer = 2, BYTE majorVer = 2){// 初始化WS2_32.dllWSADATA wsaData;WORD sockVersion = MAKEWORD(minorVer, majorVer);if (::WSAStartup(sockVersion, &wsaData) != 0){exit(0);}}/*CInitSock 的析构器*/~CInitSock(){::WSACleanup();}
};

 服务端代码:

#include "initsock.h"
#include <iostream>
using namespace std;// 初始化Winsock库
CInitSock theSock;int main()
{// 事件句柄和套节字句柄表WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS];SOCKET    sockArray[WSA_MAXIMUM_WAIT_EVENTS];int nEventTotal = 0;// 创建监听套节字SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(4567);    // 此服务器监听的端口号sin.sin_addr.S_un.S_addr = INADDR_ANY;if (::bind(sListen, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR){cout << " Failed bind()" << endl;return -1;}// 进入监听模式if (::listen(sListen, 5) == SOCKET_ERROR){cout << " Failed listen()" << endl;return 0;}cout << "服务器已启动监听,可以接收连接!" << endl;// 创建事件对象,并关联到新的套节字WSAEVENT event = ::WSACreateEvent();::WSAEventSelect(sListen, event, FD_ACCEPT | FD_CLOSE);// 添加到表中eventArray[nEventTotal] = event;sockArray[nEventTotal] = sListen;nEventTotal++;// 处理网络事件while (TRUE){// 在所有事件对象上等待int nIndex = ::WSAWaitForMultipleEvents(nEventTotal, eventArray, FALSE, WSA_INFINITE, FALSE);// 对每个事件调用WSAWaitForMultipleEvents函数,以便确定它的状态nIndex = nIndex - WSA_WAIT_EVENT_0;for (int i = nIndex; i < nEventTotal; i++){nIndex = ::WSAWaitForMultipleEvents(1, &eventArray[i], TRUE, 1000, FALSE);if (nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT){continue;}else{// 获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件WSANETWORKEVENTS event;::WSAEnumNetworkEvents(sockArray[i], eventArray[i], &event);if (event.lNetworkEvents & FD_ACCEPT)                // 处理FD_ACCEPT通知消息{if (event.iErrorCode[FD_ACCEPT_BIT] == 0){if (nEventTotal > WSA_MAXIMUM_WAIT_EVENTS){cout << " Too many connections!" << endl;continue;}sockaddr_in addrRemote;int nAddrLen = sizeof(addrRemote);SOCKET sNew = ::accept(sockArray[i], (SOCKADDR*)&addrRemote, &nAddrLen);cout << "\n与主机" << ::inet_ntoa(addrRemote.sin_addr) << "建立连接" << endl;WSAEVENT event = ::WSACreateEvent();::WSAEventSelect(sNew, event, FD_READ | FD_CLOSE | FD_WRITE);// 添加到表中eventArray[nEventTotal] = event;sockArray[nEventTotal] = sNew;nEventTotal++;}}else if (event.lNetworkEvents & FD_READ)         // 处理FD_READ通知消息{if (event.iErrorCode[FD_READ_BIT] == 0){char szText[256];int nRecv = ::recv(sockArray[i], szText, strlen(szText), 0);if (nRecv > 0){szText[nRecv] = '\0';cout << "  接收到数据:" << szText << endl;}// 向客户端发送数据char sendText[] = "你好,客户端!";if (::send(sockArray[i], sendText, strlen(sendText), 0) > 0){cout << "  向客户端发送数据:" << sendText << endl;}}}else if (event.lNetworkEvents & FD_CLOSE)        // 处理FD_CLOSE通知消息{if (event.iErrorCode[FD_CLOSE_BIT] == 0){::closesocket(sockArray[i]);for (int j = i; j < nEventTotal - 1; j++){eventArray[j] = eventArray[j + 1];sockArray[j] =  sockArray[j + 1];}nEventTotal--;}}}}}return 0;
}

客户端代码:

#include "InitSock.h"
#include <iostream>
using namespace std;CInitSock initSock;     // 初始化Winsock库int main()
{// 创建套节字SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (s == INVALID_SOCKET){cout << " Failed socket()" << endl;return 0;}// 也可以在这里调用bind函数绑定一个本地地址// 否则系统将会自动安排char address[20] = "127.0.0.1";// 填写远程地址信息sockaddr_in servAddr;servAddr.sin_family = AF_INET;servAddr.sin_port = htons(4567);// 注意,这里要填写服务器程序(TCPServer程序)所在机器的IP地址// 如果你的计算机没有联网,直接使用127.0.0.1即可servAddr.sin_addr.S_un.S_addr = inet_addr(address);if (::connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1){cout << " Failed connect() " << endl;return 0;}else {cout << "与服务器 " << address << "建立连接" << endl;}char szText[] = "你好,服务器!";if (::send(s, szText, strlen(szText), 0) > 0){cout << "  发送数据:" << szText << endl;}// 接收数据char buff[256];int nRecv = ::recv(s, buff, 256, 0);if (nRecv > 0){buff[nRecv] = '\0';cout << "  接收到数据:" << buff << endl;}// 关闭套节字::closesocket(s);return 0;
}

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

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

相关文章

手撕算法——链表

算法基础——链表-CSDN博客 一、排队顺序 题⽬来源&#xff1a;洛⾕ 题⽬链接&#xff1a;B3630 排队顺序 - 洛谷 难度系数&#xff1a;★ 1. 题目描述 2. 算法原理 本题相当于告诉了我们每⼀个点的后继&#xff0c;使⽤静态链表的存储⽅式能够很好的还原这个队列。 数组中 [1,…

RAG优化:python从零实现[吃一堑长一智]循环反馈Feedback

本文将介绍一种有反馈循环机制的RAG系统,让当AI学会"吃一堑长一智",给传统RAG装了个"后悔"系统,让AI能记住哪些回答被用户点赞/拍砖,从此告别金鱼记忆: 每次回答都像在玩roguelike:失败结局会强化下次冒险悄悄把优质问答变成新知识卡牌,实现"以…

使用cursor开发java案例——springboot整合elasticsearch

安装elasticsearch 打开cursor&#xff0c;输入如下提示词 使用springboot整合elasticsearch。其中elasticsearch服务器ip&#xff1a;192.168.236.134 管理员用户名elastic 管理员密码 PdQy_xfR2yLhpok*MK_ 监听端口9200点Accept all 使用idea打开生成的项目 &#xff0…

vue3 项目的最新eslint9 + prettier 配置

注意&#xff1a;eslint目前升级到9版本了 在 ESLint v9 中&#xff0c;配置文件已经从 .eslintrc 迁移到了 eslint.config.js 配置的方式和之前的方式不太一样了&#xff01;&#xff01;&#xff01;&#xff01; 详见自己的语雀文档&#xff1a;5、新版eslint9prettier 配…

基于FPGA的16QAM+帧同步系统verilog开发,包含testbench,高斯信道,误码统计,可设置SNR

目录 1.算法仿真效果 2.算法涉及理论知识概要 2.1 16QAM调制解调原理 2.2 帧同步 3.Verilog核心程序 4.完整算法代码文件获得 1.算法仿真效果 vivado2019.2仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 设置SNR12db 将FPGA数据导入到MATLAB显…

[学成在线]06-视频分片上传

上传视频 需求分析 教学机构人员进入媒资管理列表查询自己上传的媒资文件。 点击“媒资管理” 进入媒资管理列表页面查询本机构上传的媒资文件。 教育机构用户在"媒资管理"页面中点击 "上传视频" 按钮。 点击“上传视频”打开上传页面 选择要上传的文件…

Maven安装与环境配置

首先我们先介绍一些关于Maven的知识&#xff0c;如果着急直接看下面的安装教程。 目录 Maven介绍 Maven模型 Maven仓库 Maven安装 下载 安装步骤 Maven介绍 Apache Maven是一个项目管理和构建工具&#xff0c;它基于项目对象模型(Project Object Model , 简称: POM)的概念…

AI Tokenization

AI Tokenization 人工智能分词初步了解 类似现在这个&#xff0c;一格子 一格子&#xff0c;拼接出来的&#xff0c;一行或者一句&#xff0c;像不像&#xff0c;我们人类思考的时候组装出来的话&#xff0c;并用嘴说出来了呢。

React(四)setState原理-性能优化-ref

setState详解 实现原理 开发中我们并不能直接修改State来重新渲染界面&#xff1a; 因为修改State之后&#xff0c;希望React根据最新的State来重新渲染界面&#xff0c;但这种方式的修改React并不知道数据发生了变化&#xff1b; React并没有类似于Vue2中的Object.defineP…

SSH密钥认证 + 文件系统权限控制 + Git仓库配置+封存与解封GIT仓库

在本地服务器上实现多个用户仅通过git push操作修改仓库、禁止其他改写方式的需求&#xff0c;可以通过以下步骤实现&#xff1a; 方法概述 通过SSH密钥认证 文件系统权限控制 Git仓库配置&#xff0c;确保用户仅能通过git push命令提交修改&#xff0c;而无法通过直接操作服…

C++11中智能指针的使用(shared_ptr、unique_ptr、weak_ptr)

C11中智能指针的使用(shared_ptr、unique_ptr、weak_ptr) 一、shared_ptr原理 shared_ptr 是另一种智能指针&#xff0c;用于实现多个 shared_ptr 实例共享同一个对象的所有权。它通过内部的控制块&#xff08;通常是一个包含计数器和指向对象的指针的结构&#xff09;来管理…

2024年认证杯SPSSPRO杯数学建模B题(第二阶段)神经外科手术的定位与导航全过程文档及程序

2024年认证杯SPSSPRO杯数学建模 B题 神经外科手术的定位与导航 原题再现&#xff1a; 人的大脑结构非常复杂&#xff0c;内部交织密布着神经和血管&#xff0c;所以在大脑内做手术具有非常高的精细和复杂程度。例如神经外科的肿瘤切除手术或血肿清除手术&#xff0c;通常需要…

尝试在软考62天前开始成为软件设计师-信息系统安全

安全属性 保密性:最小授权原则(能干活的最小权限)、防暴露(隐藏)、信息加密、物理保密完整性(防篡改):安全协议、校验码、密码校验、数字签名、公证 可用性:综合保障( IP过滤、业务流控制、路由选择控制、审计跟踪)不可抵赖性:数字签名 对称加密 DES :替换移位 3重DESAESR…

Rocky9.5基于sealos快速部署k8s集群

首先需要下载 Sealos 命令行工具&#xff0c;sealos 是一个简单的 Golang 二进制文件&#xff0c;可以安装在大多数 Linux 操作系统中。 以下是一些基本的安装要求&#xff1a; 每个集群节点应该有不同的主机名。主机名不要带下划线。 所有节点的时间需要同步。 需要在 K8s …

Cursor软件如何刷新机器码流程

一.退出Cursor软件账号 打开Cursor软件&#xff0c;点击设置-->General-->Account-->Log out,现将Cursor软件上登录的账户退出。 二.将Cursor官网上登录的Cursor账户也清空掉 点击头像--> ACCOUNT SETTINGS -->Account-->Advanced-->Delete Account-->…

类与对象(中)(详解)

【本节目标】 1. 类的6个默认成员函数 2. 构造函数 3. 析构函数 4. 拷贝构造函数 5. 赋值运算符重载 6. const成员函数 7. 取地址及const取地址操作符重载 1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&…

React+Ant Design的Layout布局实现暗黑模式切换

目录 效果预览完整代码我遇到的BUG问题代码BUG1&#xff1a;暗黑模式下内容区不变成深色BUG2&#xff1a;光亮模式下的左右区域是深色 补充知识ConfigProvider是什么&#xff1f;Ant Design中的theme如何使用&#xff1f;theme 配置的常见字段主题算法通过 useToken 获取主题 效…

力扣DAY24 | 热100 | 回文链表

前言 简单 √ 是反转链表的衍生题&#xff0c;很快写完了。不过没考虑到恢复链表结构的问题。 题目 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输…

【GL010】C++

1.C中的const关键字有哪些用法&#xff1f; 1.修饰变量&#xff1a;表示变量的值不可修改。 const int a 10; 2.修饰指针&#xff1a; const int* p&#xff1a; // 指针指向的内容不可修改。 int* const p&#xff1a; // 指针本身不可修改。 const int* const…

金融行业 UE/UI 设计:解锁高效体验,重塑行业界面

在数字化浪潮中&#xff0c;金融行业的竞争日益激烈&#xff0c;用户体验&#xff08;UE&#xff09;和用户界面&#xff08;UI&#xff09;设计成为企业脱颖而出的关键。兰亭妙微凭借丰富的经验和创新的方法&#xff0c;为金融行业打造了一套行之有效的 UE/UI 解决方案&#x…