Winsock I/O 模型:性能和可扩展性的关键

目录

引言

Select模型

简介

主要特点

优点

缺点

工作原理

示例用法

WSAAsyncSelect异步I/O模型

简介

工作原理

主要步骤

优点

缺点

示例代码

WSAEventSelect事件选择模型

简介

工作原理

主要步骤

优点

缺点

示例代码

重叠I/O模型

简介

工作原理

主要优势

应用场景

示例代码

完成端口模型

简介

工作原理

主要步骤

线程池

应用场景

示例代码

结论


引言


        在网络编程领域,输入/输出(I/O)模型是数据传输的基础架构。在Windows系统中,Winsock(Windows Sockets API)提供了多种I/O模型以支持不同的网络通信需求。

        本文将详细介绍Winsock提供的五种主要I/O模型:select模型、WSAAsyncSelect异步I/O模型、WSAEventSelect事件选择模型、重叠I/O模型和完成端口模型。

Select模型

简介

        Select模型是Windows Socket中最基本的一种同步I/O模型。它通过使用Select函数,开发者可以监视一组socket的状态变化,例如可读性、可写性、错误状态等。Select模型使用轮询机制,让开发者在一个线程内管理多个socket,有效减少资源的负担。然而,由于Select模型的低效轮询机制,在处理大规模并发连接时会面临性能瓶颈。

主要特点
  • **简单易用:**Select模型的API简单易用,易于理解和使用。
  • **多socket管理:**Select模型可以同时监视多个socket,并等待其中任何一个变为可读、可写或发生异常。
  • **跨平台支持:**Select模型在大多数操作系统上都得到了广泛的支持,包括Windows、Linux和macOS。
优点
  • **易于使用:**Select模型的简单API和直接的方法使其成为开发人员的理想选择。
  • **资源效率:**通过在单个线程内管理多个socket,Select模型最大限度地减少了资源消耗和开销。
  • **跨平台兼容性:**Select模型在不同平台上的广泛支持确保了其在各种环境中的适用性。
缺点
  • **轮询效率低下:**Select模型的轮询机制,即顺序检查每个socket的状态,会导致性能下降,尤其是在处理大量socket时。
  • **并发限制:**Select模型的单线程特性可能会限制并发性,从而阻碍对高水平并发I/O操作要求苛刻的应用程序的性能。
  • **可扩展性问题:**随着连接和I/O操作数量的增加,Select模型的轮询机制可能会不堪重负,导致可扩展性问题。
工作原理

        Select模型通过使用称为“fd_set”的数据结构来存储要监视的socket描述符来工作。fd_set结构包含三个集合:

  • **readfds:**包含可读socket描述符。
  • **writefds:**包含可写socket描述符。
  • **exceptfds:**包含遇到错误的socket描述符。

        开发人员可以将感兴趣的socket描述符添加到相应的fd_set中。然后,他们调用Select函数,并将fd_set作为参数传递。Select函数将阻塞,直到至少一个socket变为可读、可写或遇到错误。返回后,Select函数会更新fd_set结构,指示哪些socket已过渡到准备状态。然后,开发人员可以检查修改后的fd_set来处理相应的I/O操作。

示例用法

以下代码片段演示了使用Select模型监视两个socket的基本用法:

#include <winsock.h>int main() {// 初始化WinsockWSADATA wsaData;int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != 0) {printf("WSAStartup failed: %d\n", iResult);return 1;}// 创建socketSOCKET sock1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock1 == INVALID_SOCKET) {printf("socket failed: %d\n", WSAGetLastError());WSACleanup();return 1;}SOCKET sock2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock2 == INVALID_SOCKET) {printf("socket failed: %d\n", WSAGetLastError());closesocket(sock1);WSACleanup();return 1;}// 绑定socketsockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(8080);serverAddr.sin_addr.s_addr = INADDR_ANY;int iBindResult1 = bind(sock1, (SOCKADDR*)&serverAddr, sizeof(serverAddr));if (iBindResult1 == SOCKET_ERROR) {printf("bind failed: %d\n", WSAGetLastError());closesocket(sock1);closesocket(sock2);WSACleanup();return 1;}int iBindResult2 = bind(sock2, (SOCKADDR*)&serverAddr, sizeof(serverAddr));if (iBindResult2 == SOCKET_ERROR) {printf("bind failed: %

WSAAsyncSelect异步I/O模型

简介

        WSAAsyncSelect 异步 I/O 模型提供了一种异步的方式来通知应用程序 socket 的状态变化。与 Select 模型的轮询机制不同,WSAAsyncSelect 使用消息队列来传递通知,使应用程序无需主动查询 socket 的状态即可获知其变化。

工作原理

        WSAAsyncSelect 模型的核心是将 socket 与一个消息队列关联起来。当 socket 的状态发生变化时,例如有数据可读或可写,系统就会向该消息队列发送一条消息。应用程序可以通过处理消息队列中的消息来响应相应的 I/O 操作。

主要步骤
  1. **创建消息队列:**应用程序首先需要创建一个消息队列,用于接收来自系统的通知消息。
  2. **关联 socket 和消息队列:**使用 WSAAsyncSelect 函数将 socket 与消息队列关联起来。
  3. **设置事件:**应用程序可以设置 WSAAsyncSelect 函数的参数,指定要通知的事件类型,例如可读、可写或错误。
  4. **处理消息:**应用程序需要有一个消息处理循环来不断地从消息队列中获取消息。
  5. **关闭 socket:**当应用程序不再需要使用 socket 时,需要使用 closesocket 函数关闭 socket 并取消其与消息队列的关联。
优点
  • **异步通知:**应用程序无需主动查询 socket 的状态,可以提高应用程序的响应速度和效率。
  • **减少资源占用:**应用程序无需使用轮询机制来监视 socket 状态,可以减少 CPU 资源的占用。
  • **易于实现:**WSAAsyncSelect 模型的 API 相对简单,易于理解和实现。
缺点
  • **消息队列延迟:**由于依赖消息队列传递通知,可能会存在消息处理的延迟。
  • **可扩展性问题:**在高并发情况下,消息队列可能会成为性能瓶颈。
示例代码

以下代码演示了如何使用 WSAAsyncSelect 模型来监视一个 socket:

#include <winsock.h>int main() {// 初始化 WinsockWSADATA wsaData;int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != 0) {printf("WSAStartup failed: %d\n", iResult);return 1;}// 创建 socketSOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock == INVALID_SOCKET) {printf("socket failed: %d\n", WSAGetLastError());WSACleanup();return 1;}// 创建消息队列MSGQUEUE hMsgQueue = CreateMsgQueue(NULL, 0, 0);if (hMsgQueue == NULL) {printf("CreateMsgQueue failed: %d\n", GetLastError());closesocket(sock);WSACleanup();return 1;}// 关联 socket 和消息队列WSAAsyncSelect(sock, hMsgQueue, WM_SOCKET_NOTIFY);// 设置事件WSAEventSelect(sock, FD_READ);// 消息处理循环MSG msg;while (GetMessage(&msg, NULL, 0, 0)) {switch (msg.message) {case WM_SOCKET_NOTIFY: {WPARAM wParam = msg.wParam;LPARAM lParam = msg.lParam;// 处理 socket 事件switch (wParam) {case FD_READ:// 处理可读事件break;case FD_WRITE:// 处理可写事件break;case FD_CLOSE:// 处理连接关闭事件break;case FD_ERROR:// 处理错误事件break;}break;}default:DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);}}// 关闭 socketclosesocket(sock);// 关闭消息队列CloseMsgQueue(hMsgQueue);// 清理 WinsockWSACleanup();return 0;
}

WSAEventSelect事件选择模型

简介

        WSAEventSelect 模型是 Winsock 提供的另一种事件驱动的异步 I/O 方式。与 WSAAsyncSelect 模型不同,WSAEventSelect 模型使用事件对象来表示 socket 的状态变化,而不是使用消息队列。这种模型允许开发者为每个 socket 创建一个事件对象,并将 socket 的状态变化与这些事件关联。随后,开发者可以使用 WaitForMultipleObjects 等函数来等待任何一个事件的触发。这种模型使得事件管理更加简洁,并且可以提供出色的性能表现。

工作原理

        WSAEventSelect 模型的核心是将 socket 与一个或多个事件对象关联起来。当 socket 的状态发生变化时,例如有数据可读或可写,系统就会将该事件的状态设置为已触发。应用程序可以使用 WaitForMultipleObjects 等函数来等待任何一个事件的触发。当一个事件被触发时,应用程序可以根据该事件的类型来执行相应的 I/O 操作。

主要步骤
  1. **创建事件对象:**应用程序首先需要为每个 socket 创建一个事件对象。
  2. **关联 socket 和事件对象:**使用 WSAEventSelect 函数将 socket 与事件对象关联起来。
  3. **设置事件:**应用程序可以设置 WSAEventSelect 函数的参数,指定要通知的事件类型,例如可读、可写或错误。
  4. **等待事件:**应用程序可以使用 WaitForMultipleObjects 等函数来等待任何一个事件的触发。
  5. **处理事件:**当一个事件被触发时,应用程序可以使用 GetEventObjectIdentity 函数来确定哪个 socket 的状态发生了变化,然后根据该事件的类型来执行相应的 I/O 操作。
  6. **关闭 socket:**当应用程序不再需要使用 socket 时,需要使用 closesocket 函数关闭 socket 并取消其与事件对象的关联。
优点
  • **简洁的事件管理:**WSAEventSelect 模型使用事件对象来表示 socket 的状态变化,使得事件管理更加简洁。
  • **出色的性能表现:**WSAEventSelect 模型可以提供出色的性能表现,因为它避免了消息队列的开销。
  • **易于扩展:**WSAEventSelect 模型易于扩展,因为它允许为每个 socket 创建多个事件对象。
缺点
  • **编程复杂度略高:**与 Select 模型相比,WSAEventSelect 模型的编程复杂度略高,因为它需要创建和管理事件对象。
  • **需要额外的内存分配:**事件对象的创建需要额外的内存分配。
示例代码

以下代码演示了如何使用 WSAEventSelect 模型来监视一个 socket:

#include <winsock.h>int main() {// 初始化 WinsockWSADATA wsaData;int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != 0) {printf("WSAStartup failed: %d\n", iResult);return 1;}// 创建 socketSOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock == INVALID_SOCKET) {printf("socket failed: %d\n", WSAGetLastError());WSACleanup();return 1;}// 创建事件对象WSAEVENT hEvent = WSAEventCreate(NULL, TRUE, TRUE, NULL);if (hEvent == NULL) {printf("WSAEventCreate failed: %d\n", GetLastError());closesocket(sock);WSACleanup();return 1;}// 关联 socket 和事件对象WSAEventSelect(sock, hEvent, FD_READ | FD_WRITE);// 等待事件DWORD dwWaitResult = WaitForMultipleObjects(1, &hEvent, TRUE, INFINITE);if (dwWaitResult == WAIT_FAILED) {printf("WaitForMultipleObjects failed: %d\n", GetLastError());WSACloseEvent(hEvent);closesocket(sock);WSACleanup();return 1;}// 处理事件WSAEVENT hTriggeredEvent = NULL;DWORD dwEventCount = 0;BOOL bSuccess = WSAEnumEvents(sock, NULL, &hTriggeredEvent, 1, &dwEventCount);if (bSuccess && dwEventCount > 0) {DWORD dwEventFlags;bSuccess = WSAEventGetInfo(hTriggeredEvent, 0, NULL, &dwEventFlags);

重叠I/O模型

简介

        重叠 I/O 模型是 Windows 独有的一种先进的异步 I/O 技术。它允许 I/O 操作在后台执行,应用程序无需等待 I/O 操作完成即可继续处理其他任务。与传统的阻塞 I/O 模型相比,重叠 I/O 模型可以显著提高应用程序的性能,尤其是在处理大量 I/O 操作的网络应用程序中。

工作原理

        重叠 I/O 模型的核心是使用 OVERLAPPED 结构体来管理 I/O 操作。OVERLAPPED 结构体包含以下成员:

  • hEvent:用于通知应用程序 I/O 操作完成的事件句柄。
  • Internal:保留供系统内部使用。
  • Offset:用于指示 I/O 操作要从文件或缓冲区的哪个位置开始。
  • InternalHigh:保留供系统内部使用。
  • Union:包含指向用于 I/O 操作的缓冲区的指针。

        应用程序可以使用 WSARecvWSASend 等函数来发起重叠 I/O 操作。这些函数会将 I/O 操作的参数和 OVERLAPPED 结构体作为参数传递。系统会将 I/O 操作排队并将其置于后台执行。当 I/O 操作完成时,系统会将 hEvent 事件设置为已触发状态,并通知应用程序。

主要优势
  • **提高性能:**重叠 I/O 模型可以显著提高应用程序的性能,因为应用程序无需等待 I/O 操作完成即可继续处理其他任务。
  • **提高响应速度:**重叠 I/O 模型可以提高应用程序的响应速度,因为应用程序可以同时处理多个 I/O 操作。
  • **降低资源占用:**重叠 I/O 模型可以降低应用程序对 CPU 资源的占用,因为 I/O 操作是在后台执行的。
应用场景

        重叠 I/O 模型适用于需要处理大量 I/O 操作的应用程序,例如:

  • **网络应用程序:**Web 服务器、客户端-服务器应用程序、P2P 应用程序等。
  • **文件 I/O 密集型应用程序:**数据库应用程序、视频编辑软件、大型文件传输应用程序等。
示例代码

以下代码演示了如何使用重叠 I/O 模型从套接字中接收数据:

#include <winsock.h>int main() {// 初始化 WinsockWSADATA wsaData;int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != 0) {printf("WSAStartup failed: %d\n", iResult);return 1;}// 创建套接字SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock == INVALID_SOCKET) {printf("socket failed: %d\n", WSAGetLastError());WSACleanup();return 1;}// 绑定套接字sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(8080);serverAddr.sin_addr.s_addr = INADDR_ANY;int iBindResult = bind(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));if (iBindResult == SOCKET_ERROR) {printf("bind failed: %d\n", WSAGetLastError());closesocket(sock);WSACleanup();return 1;}// 监听套接字int iListenResult = listen(sock, 5);if (iListenResult == SOCKET_ERROR) {printf("listen failed: %d\n", WSAGetLastError());closesocket(sock);WSACleanup();return 1;}// 接受连接sockaddr_in clientAddr;int clientAddrLen = sizeof(clientAddr);SOCKET clientSock = accept(sock, (SOCKADDR*)&clientAddr, &clientAddrLen);if (clientSock == INVALID_SOCKET) {printf("accept failed: %d\n", WSAGetLastError());closesocket(sock);WSACleanup();return 1;}// 创建事件对象WSAEVENT hEvent = WSAEventCreate(NULL, TRUE, TRUE, NULL);

完成端口模型

简介

        完成端口模型是 Windows Sockets 中最复杂但也是最强大的 I/O 模型。它充分利用了多核处理器的能力,提供了一个可伸缩的高性能 I/O 操作解决方案。与其他 I/O 模型相比,完成端口模型具有以下优势:

  • **高性能:**完成端口模型可以充分利用多核处理器的能力,显著提高 I/O 操作的性能。
  • **可伸缩性:**完成端口模型可以处理大量并发连接,并随着硬件的升级而扩展。
  • **低延迟:**完成端口模型可以提供低延迟的 I/O 操作,非常适合对延迟敏感的应用程序。
工作原理

        完成端口模型的核心是使用 CreateIoCompletionPort 函数创建一个或多个完成端口。完成端口是一个内核对象,用于存储已完成 I/O 操作的通知。应用程序可以使用 AssociateSocket 函数将一个或多个套接字与完成端口关联起来。

        当一个套接字上的 I/O 操作完成时,系统会将一个 IO_COMPLETION_RESULT 结构体发送到与该套接字关联的完成端口。应用程序可以使用 GetQueuedCompletionPort 函数来检索完成端口队列中的通知。

主要步骤
  1. **创建完成端口:**使用 CreateIoCompletionPort 函数创建一个或多个完成端口。
  2. **关联套接字:**使用 AssociateSocket 函数将一个或多个套接字与完成端口关联起来。
  3. **发起 I/O 操作:**使用 WSASendWSARecv 等函数发起 I/O 操作,并将 OVERLAPPED 结构体传递给这些函数。
  4. **检索完成通知:**使用 GetQueuedCompletionPort 函数检索完成端口队列中的通知。
  5. **处理完成通知:**根据 IO_COMPLETION_RESULT 结构体中的信息处理完成的 I/O 操作。
线程池

        完成端口模型通常与线程池技术结合使用。线程池是一种管理线程的技术,可以有效地分配处理器资源进行并行计算。在完成端口模型中,应用程序可以使用线程池来处理完成的 I/O 操作。每个线程池中的线程都可以从完成端口队列中检索通知并处理完成的 I/O 操作。

应用场景

完成端口模型适用于需要处理大量并发 I/O 操作的应用程序,例如:

  • **网络应用程序:**Web 服务器、高性能网络应用、游戏服务器等。
  • **文件 I/O 密集型应用程序:**数据库应用程序、视频编辑软件、大型文件传输应用程序等。
示例代码

以下代码演示了如何使用完成端口模型从套接字中接收数据:

#include <winsock.h>int main() {// 初始化 WinsockWSADATA wsaData;int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != 0) {printf("WSAStartup failed: %d\n", iResult);return 1;}// 创建完成端口HANDLE hCompletionPort = CreateIoCompletionPort(NULL, NULL, 0, 0);if (hCompletionPort == NULL) {printf("CreateIoCompletionPort failed: %d\n", GetLastError());WSACleanup();return 1;}// 创建套接字SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock == INVALID_SOCKET) {printf("socket failed: %d\n", WSAGetLastError());CloseHandle(hCompletionPort);WSACleanup();return 1;}// 绑定套接字sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(8080);serverAddr.sin_addr.s_addr = INADDR_ANY;int iBindResult = bind(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));if (iBindResult == SOCKET_ERROR) {printf("bind failed: %d\n", WSAGetLastError());closesocket(sock);CloseHandle(hCompletionPort);WSACleanup();return 1;}// 监听套接字int iListenResult = listen(sock, 5);if (iListenResult == SOCKET_ERROR) {

结论


        Winsock为Windows下的网络编程提供了多样化的I/O模型,每种模型都适用于不同场景的需求。无论是简单的select模型,还是高效的完成端口模型,了解它们的工作方式、优缺点对于开发高质量的网络应用程序都至关重要。掌握这些I/O模型,将有助于你建构出更稳定、更高性能的网络通信解决方案。

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

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

相关文章

网络编程 一

一、UDP socket api的使用 Java 把系统原生的封装了. 核心的类有两个: 1 -> DatagramSocket 操作系统中,有一类文件,就叫socket文件. socket文件,抽象表示了 " 网卡"这样的硬件设备. 进行网络通信最核心的硬件设备网卡 通过网卡发送数据,就是写…

各手机品牌【短信收件箱数据库列名】对比:inbox的column横向对比

参考资料: https://blog.csdn.net/qq_35427437/article/details/85678647 https://www.cnblogs.com/bill-technology/p/4130917.html <font colorred>threads是存放会话的数据表&#xff0c;sms是存放短信的数据表&#xff0c;pdu是存放彩信的数据表</font> | 含义…

0基础从前端到Web3 —— Mine Clearance Frontend(二)

在一的基础上继续往下&#xff0c;本篇主要是链上调用部分&#xff0c;让整个项目可以进行最基本的扫雷游戏。 S u i M o v e \mathit {Sui\ Move} Sui Move 链上部署的自主实现的简单扫雷游戏可以点击查看&#xff0c;只不过这里将区域大小扩大为了 10 20 \text {10}\ \tim…

力扣Hot100-73矩阵置零(标记数组)

给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]示例 2&#xff1a; 输入&…

大模型面试--大模型(LLMs)基础面

大模型&#xff08;LLMs&#xff09;基础面 1. 目前主流的开源模型体系有哪些&#xff1f; 目前主流的开源大模型体系有以下几种&#xff1a; 1. Transformer 系列 Transformer 模型是深度学习中的一类重要模型&#xff0c;尤其在自然语言处理&#xff08;NLP&#xff09;领…

JavaWeb Sevelet学习 创建Sevelet程序

Servlet 是JavaWeb中的开发动态Web一门技术 是由Sun公司提供的一个接口&#xff0c;允许开发者编写运行在服务器&#xff08;Tomcat&#xff09;上的Java程序&#xff0c;这些程序可以 生成动态网页内容&#xff0c; 响应客户端的请求。简单来说&#xff0c;Servlet就是Java E…

今日arXiv最热大模型论文:LoRA又有新用途,学得少忘得也少,成持续学习关键!

自大模型&#xff08;LLM&#xff09;诞生以来&#xff0c;苦于其高成本高消耗的训练模式&#xff0c;学界和业界也在努力探索更为高效的参数微调方法。其中Low-Rank Adaptation&#xff08;LoRA&#xff09;自其诞生以来&#xff0c;就因其较低的资源消耗而受到广泛关注和使用…

Spring MVC八股文面试题及参考答案(4万字长文)

目录 什么是Spring MVC? 解释MVC模式及其在Spring MVC中的实现。 Spring MVC和Struts的区别是什么?

瑞芯微RV1126——交叉编译与移植

一、搭建这个nfs服务挂载 (1) sudo apt install nfs-kernel-server (2) 然后在你的ubuntu创建一个nfs共享目录&#xff1a; (3) sudo /etc/init.d/nfs-kernel-server restart 重启nfs服务 (4) 修改配置文件: sudo vim /etc/exports 在这个配置文件里面添加&#xff1a;/hom…

C语言/数据结构——每日一题(设计循环队列)

一.前言 上一次我们分享了关于队列的基本实现——https://blog.csdn.net/yiqingaa/article/details/139033067?spm1001.2014.3001.5502 现在我们将使用队列知识来解决问题——设计循环队列&#xff1a;https://leetcode.cn/problems/design-circular-queue/submissions/533299…

50.WEB渗透测试-信息收集-CDN识别绕过(3)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;49.WEB渗透测试-信息收集-CDN识别绕过&#xff08;2&#xff09; 关于cdn的识别方法内容…

Leecode热题100--73:矩阵置零

题目&#xff1a; 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 C&#xff1a; 思路&#xff1a; 可以使用两个数组来记录哪些行和列需要被置零。 首先&#xff0c;我们遍历整个矩阵&#xff0c;…

设计模式--享元模式

引言 享元模式&#xff08;Flyweight Pattern&#xff09;作为一种高效节省内存的结构型设计模式&#xff0c;其核心在于通过共享技术有效支持大量细粒度对象的重用&#xff0c;从而减少内存占用&#xff0c;提高系统性能。特别是在处理大量相似对象的场景下&#xff0c;享元模…

智慧监狱人员行为识别监测系统

智慧监狱人员行为识别监测系统是基于神经网络AI视觉智能分析算法开发的技术。智慧监狱人员行为识别监测系统利用现场监控摄像头&#xff0c;通过对人体活动骨架的结构化分析&#xff0c;根据人体运动轨迹定义了多种异常行为&#xff0c;从而实现对监舍内的静坐不动、离床、攀高…

Tron节点监控脚本使用说明

文章目录 一、配置二、脚本编写2.1 Python脚本--监控节点是否正在同步2.1.1 pyton脚本脚本示例2.1.2 使用说明2.2.3 脚本监控内容说明 2.2 Shell脚本--综合情况监控2.2.1 shell脚本示例2.2.2 使用说明2.2.3 脚本监控内容说明 最近搭建了TRON节点&#xff0c;为了防止节点在生产…

Mixiy(米思齐)安装

Mixiy(米思齐)安装 官网地址&#xff1a;爱上米思齐 打开官网&#xff0c;选择下图的软件进行下载 复制提取码&#xff0c;点击链接跳转到网盘进行下载&#xff0c;选择(RC4完整版) 下载完成后&#xff0c;解压到合适的位置&#xff0c;进入文件夹&#xff0c;双击Mixly.exe即…

Docker 部署Jenkins

1、运行镜像 docker run --namejenkins \--restartalways \--privilegedtrue \-u root \-p 8080:8080 \-p 50000:50000 \-v /home/docker/jenkins/jenkins_home:/var/jenkins_home \-v /usr/bin/docker:/usr/bin/docker \-v /var/run/docker.sock:/var/run/docker.sock \-e TZ…

【Crypto】MD5

文章目录 MD5解题感悟 MD5 提示的很明显MD5 小小flag&#xff0c;拿下&#xff01; 解题感悟 没啥感悟…

Java输入与输出详解

Java输入和输出 前言一、Java打印Hello World二、输出到控制台基本语法代码示例格式化字符串 三、从键盘输入读入一个字符正确写法 使用 Scanner 读取字符串/整数/浮点数使用 Scanner 循环读取 N 个数字 前言 推荐一个网站给想要了解或者学习人工智能知识的读者&#xff0c;这…

使用 Java 和 MyBatis 实现动态排序的多表查询

相关 java实现一个根据字段和排序方式进行排序 java实现自定义排序 自定义动态排序 前言 在Web开发中&#xff0c;前端通常会传递一些参数来决定数据的排序方式&#xff0c;例如排序字段和排序方向。本文将展示如何在 Java 项目中结合 MyBatis 实现动态排序&#xff0c;尤其…