【网络编程】WSAAsyncSelect 模型
十、基于I/O模型的网络开发
接着上次的博客继续分享:select模型
10.8 异步选择模型WSAAsyncSelect
10.8.1 基本概念
-
WSAAsyncSelect模型是Windows socket的一个异步I/O 模型,利用这个模型,应用程序 可在一个套接字上接收以Windows 消息为基础的网络事件通知。
-
Windows sockets应用程序在 创建套接字后,调用WSAAsyncSelect 函数注册感兴趣的网络事件,当该事件发生时Windows 窗口收到消息,应用程序就可以对接收到的网络事件进行处理了。
-
利用WSAAsyncSelect 函数, 将socket 消息发送到hWnd 窗口上,然后在那里处理相应的FD_READ 、FD_WRITE 等消息。
-
WSAAsyncSelect 模型与select 模型的相同点是它们都可以对多个套接字进行管理。
-
但它 们也有不小的区别。首先WSAAsyncSelect 模型是异步的,且通知方式不同。更重要的一点是: WSAAsyncSelect 模型应用在基于消息的Windows 环境下,使用该模型时必须创建窗口,而 select 模型可以广泛应用在UNIX/Linux 系统,使用该模型不需要创建窗口。最后一点区别是:应用程序在调用WSAAsyncSelect 函数后,套接字就被设置为非阻塞状态;而使用select 函数 不改变套接字的工作方式。
-
由于要关联一个Windows 窗口来接收消息,因此如果处理成千上万的套接字就力不从心 了。这也是该模型的一个缺点。另外,由于调用WSAAsyncSelect 后,套接字被设为非阻塞模 式,那么其他一些函数调用不一定能成功返回,必须要对这些函数的调用返回做处理。对于这 一点,可以从accept() 、receive() 和 send() 等函数的调用中得到验证。
-
WSAAsyncSelect模型也有其优点,即提供了读写数据能力的异步通知。而且,该模型为 确保接收所有数据提供了很好的机制,通过注册FD_CLOSE网络事件,可以从容关闭服务器与客户端的连接,保证了数据的全部接收。
10.8.2 WSAAsyncSelect函数
WSAAsyncSelect函数会自动将套接字设置为非阻塞模式,并且把发生在该套接字上且是 你所感兴趣的事件以Windows 消息的形式发送到指定的窗口。
WSAAsyncSelect函数声明如下:
int WSAAsyncSelect(in SOCKET s,in HWND hWnd,__in unsigned int wMsg,__in long lEvent);
-
s: 标识一个需要事件通知的套接口的描述符。
-
hWnd: 标识一个在网络事件发生时需要接收消息的窗口句柄。
-
wMsg: 在网络事件发生时要接收的消息。
-
IEvent: 位屏蔽码,用于指明应用程序感兴趣的网络事件集合。IEvent 参数可取下列 值:
-
- FD_READ: 欲接收读准备好的通知。发生FD_READ 的条件是:
-
-
- 调 用recv 或 者recvfrom 函数后,仍然有数据可读。
-
-
-
- 调用WSAAsyncSelect 有数据可读。
-
-
- FD_WRITE: 欲接收写准备好的通知。发生FD_WRITE 的条件是:
-
-
- 当调用WSAAsyncSelect 函数时,如果调用能够发送数据。
-
-
-
- 调用connect 或 者accept 函数后,当连接已经建立时。
-
-
-
- 调用send 或 者sendto, 返 回WSAWOULDBLOCK 错误码,再次调用send 或 者sendto 函数可能成功时。
-
-
- FD_OOB: 欲接收带边数据到达的通知。
-
- FD_ACCEPT: 欲接收将要连接的通知。
-
- FD_CONNECT: 欲接收已连接好的通知。
-
- FD_CLOSE: 欲接收套接口关闭的通知。发生FD CLOSE 的条件是:
-
-
- 当调用WSAAsyncSelect 函数时,套接字连接关闭时。
-
-
-
- 对方执行从容关闭后,没有数据可读时,如果数据已经到达并等待读取,FD_CLOSE 事件不会被发送,直到所有数据都被接收。
-
-
-
- 调用shutdown 函数执行从容关闭,对方应答FIN 后,此时无数据可读。
-
-
-
- 对方结束了连接,并且lparam 包 含WSAECONNRESET 错误时。
-
-
- FD_QOS: 欲接收套接字服务质量发生变化的通知。
-
- FD_GROUP_QOS: 欲接收套接字组服务质量发生变化的通知。
-
- FD_ADDRESS_LIST_CHANGE: 欲接收针对套接字的协议簇,本地地址列表发生变化的通知。
-
- FD ROUTING INTERFACE CHANGE: 欲在指定方向上与路由接口发生变化的通知 。
如果函数成功就返回0,如果出错就返回 SOCKET_ERROR,此时可用函数 WSAGetLastError 获取更多信息。
可根据需要同时注册多个网络事件,这时要把网络事件类型执行按位或(OR) 运算,然 后将它们分配给 IEvent 参数。例如,应用程序希望在套接字上接收连接完成、数据可读和套 接字关闭的网络事件,可调用如下函数:
WSAAsyncSelect(s, hwnd, WM_SOCKET, FD_CONNECT | FD_READ | FD_CLOSE);
当该套接字连接完成、有数据可读或者套接字关闭的网络事件发生时,就会有 WM_SOCKET消息发送给窗口句柄为hwnd 的窗口。
值得注意的是,启动一个 WSAAsyncSelect 将使为同一个套接口启动的所有先前的 WSAAsyncSelect 作废。
使用WSAAsyncSelect 函数需要注意的地方:
- (1)调用该函数后,套接字被设置为非阻塞模式,要想恢复为阻塞模式,必须再次调用 该函数,取消掉注册过的事件,再调用ioctlsocket 设为阻塞模式。如果要取消所有的网络事件通知,告知windows sockets实现不再为该套接字发送任何网
络事件相关的消息,要以参数IEvent 值为0调用函数,即
WSAAsyncSelect(s, hwnd,0,0)
尽管应用程序调用上述函数取消了网络事件通知,但是在应用程序消息队列中,可能还有 网络消息在排队。所以调用上述函数取消网络事件消息后,应用程序还应该继续准备接收网络 事 件 。
- (2)消息函数的wParam 参数为事件发生的套接字,LParam 对应错误消息和相应的事件, 可以调用宏WSAGETSELECTERROR(IParam) 、WSAGETSELECTEVENT(IParam) 来获取具体 的 信 息 。
- (3)多次调用WSAAsyncSelect 函数在同一个套接字上注册不同的事件(多次调用采用 同样或者不同样的消息),最后一次调用将取消前面注册的事件。比如前后两次调用:
WSAAsyncSelect(s, hwnd, WM_SOCKET, FD_READ);
WSAAsyncSelect(s, hwnd, WM_SOCKET, FD_WRITE);
此时虽然消息相同,都是WM_SOCKET, 但是应用程序只能接收到FD_WRITE 网络事件。
还有一种情况是消息不同、网络事件也不同,比如:
WSAAsyncSelect(s, hwnd, wMsg1, FD_READ);
WSAAsyncSelect(s, hwnd, wMsg2, FD_WRITE);
第二次函数调用依旧将会取消第一次函数调用的作用,只有 FD_WRITE 网络事件通过wMsg2 通知到窗口。
这也是很多初学者发现接收不到网络事件的原因。因为最后一次调用将取消前面注册的事 件。
- (4)使用accept 函数建立的套接字与监听套接字具有同样的属性,也就是说,在监听套 接字上注册的事件同样会对建立连接的套接字起作用,如果一个监听套接字请求 FD_READ 和 FD_WRITE 网络事件,那么在该监听套接字上接受的任何套接字也会请求 FD_READ 和 FD_WRITE 网络事件,以及发送同样的消息。
我们一般会在监听套接字建立连接后重新为其注册事件。
-
(5)为一个FD_READ网络事件不要多次调用recv(函数,如果应用程序为一个FD_READ 网络事件调用多个recv()函数,就会使得该应用程序收到多个FD_READ 网络事件。如果在一 次接收FD_READ 网络事件时需要调用多次 recv()函数,应用程序就应该在调用recv()函数之 前关闭FD_READ消息。
-
(6)使用FD_CLOSE 事件来判断套接字是否已经关闭,错误代码指示套接字是从容关闭 还是硬关闭:错误码为0,代表从容关闭;错误码为WSAECONNERESET, 则为硬关闭。如 果套接字从容关闭,数据全部接收,应用程序就会收到FD_CLOSE。
-
(7)发送数据出现失败。一个应用程序当接收到第一个FD_WRITE 网络事件后,便认为 在该套接字上可以发送数据。当调用输出函数发送数据时,会收到 WSAEWOULDBLOCKE 错误。经过这样的失败后,要在下一次接收到FD_WRITE网络事件后再次发送数据,才能够 将数据成功发送。
10.8.3 实战WSAAsyncSelect 模型
WSAAsyncSelect 传参需要窗口句柄。为了简化代码,这里直接创建了一个mfc 对话框程 序,用m_hwnd 给 WSAAsyncSelect 传参。对话框类名为WSAAsyncSelecDlg。
服务端
#define _WINSOCK_DEPRECATED_NO_WARNINGS#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")#define WM_SOCKET (WM_USER + 101)//-------------------窗口过程----------------------
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{switch (uMsg){case WM_SOCKET:{SOCKET ss = wParam; // wParam 参数标志了网络事件发生的套接口long event = WSAGETSELECTEVENT(lParam); // 事件int error = WSAGETSELECTERROR(lParam); // 错误码if (error){closesocket(ss);return 0;}switch (event){case FD_ACCEPT: //-----①连接请求到来{sockaddr_in Cadd;int Cadd_len = sizeof(Cadd);SOCKET sNew = accept(ss, (sockaddr*)&Cadd, &Cadd_len);if (sNew == INVALID_SOCKET){MessageBox(hwnd, L"调用accept()失败!", L"标题栏提示", MB_OK);}else{WSAAsyncSelect(sNew, hwnd, WM_SOCKET, FD_READ | FD_CLOSE);}} break;case FD_READ: //-----②数据发送来{char cbuf[256];memset(cbuf, 0, sizeof(cbuf));int cRecv = recv(ss, cbuf, sizeof(cbuf), 0);if ((cRecv == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET) || cRecv == 0){MessageBox(hwnd, L"调用recv()失败!", L"标题栏提示", MB_OK);closesocket(ss);}else if (cRecv > 0){// 转换消息为宽字符wchar_t wbuf[256];MultiByteToWideChar(CP_ACP, 0, cbuf, -1, wbuf, sizeof(wbuf) / sizeof(wchar_t));MessageBox(hwnd, wbuf, L"收到的信息", MB_OK);char Sbuf[] = "Hello client! I am server";int isend = send(ss, Sbuf, sizeof(Sbuf), 0);if (isend == SOCKET_ERROR || isend <= 0){MessageBox(hwnd, L"发送消息失败!", L"标题栏提示", MB_OK);}else{MessageBox(hwnd, L"已经发信息到客户端!", L"标题栏提示", MB_OK);}}} break;case FD_CLOSE: //----③关闭连接{closesocket(ss);}break;}}break;case WM_CLOSE:if (IDYES == MessageBox(hwnd, L"是否确定退出?", L"message", MB_YESNO))DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, uMsg, wParam, lParam);}return 0;
}//----------------WinMain()函数------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{WNDCLASS wc;wc.style = CS_HREDRAW | CS_VREDRAW;wc.lpfnWndProc = WindowProc;wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hInstance = hInstance;wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);wc.hCursor = LoadCursor(NULL, IDC_ARROW);HBRUSH hbrush = CreateSolidBrush(RGB(0, 128, 25));wc.hbrBackground = hbrush;wc.lpszMenuName = NULL;wc.lpszClassName = L"Test";//---注册窗口类(使用宽字符版本函数)---- RegisterClassW(&wc);//---创建窗口---- HWND hwnd = CreateWindowW(L"Test", L"WSAAsyncSelect模型-服务端窗口", WS_SYSMENU, 300, 0, 600, 400, NULL, NULL, hInstance, NULL);if (hwnd == NULL){MessageBoxW(NULL, L"创建窗口出错", L"标题栏提示", MB_OK);return 1;}//---显示窗口---- ShowWindow(hwnd, SW_SHOWNORMAL);UpdateWindow(hwnd);//---初始化WSA---WSADATA wsaData;WORD wVersionRequested = MAKEWORD(2, 2);if (WSAStartup(wVersionRequested, &wsaData) != 0){MessageBoxW(NULL, L"WSAStartup() Failed", L"调用失败", 0);return 1;}SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (s == INVALID_SOCKET){MessageBoxW(NULL, L"socket() Failed", L"调用失败", 0);return 1;}sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(6000);sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");if (bind(s, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR){MessageBoxW(NULL, L"bind() Failed", L"调用失败", 0);return 1;}if (listen(s, 3) == SOCKET_ERROR){MessageBoxW(NULL, L"listen() Failed", L"调用失败", 0);return 1;}elseMessageBoxW(hwnd, L"进入监听状态!", L"标题栏提示", MB_OK);WSAAsyncSelect(s, hwnd, WM_SOCKET, FD_ACCEPT | FD_CLOSE);//---消息循环----MSG msg;while (GetMessageW(&msg, 0, 0, 0)){TranslateMessage(&msg);DispatchMessageW(&msg);}closesocket(s);WSACleanup();return msg.wParam;
}
客户端
#define _WINSOCK_DEPRECATED_NO_WARNINGS#include<stdlib.h>
#include<WINSOCK2.H>
#include <windows.h>
#include <process.h> #include<iostream>
#include<string>
using namespace std;#define BUF_SIZE 64
#pragma comment(lib,"wS2_32.lib")void recv(PVOID pt)
{SOCKET sHost = *((SOCKET*)pt);while (true){char buf[BUF_SIZE];//清空接收数据的缓冲区memset(buf, 0, BUF_SIZE);int retVal = recv(sHost, buf, sizeof(buf), 0);if (SOCKET_ERROR == retVal){int err = WSAGetLastError();//无法立即完成非阻塞Socket上的操作if (err == WSAEWOULDBLOCK){Sleep(1000);//printf("\nwaiting reply!");continue;}else if (err == WSAETIMEDOUT || err == WSAENETDOWN || err == WSAECONNRESET)//已建立连接{printf("recv failed!");closesocket(sHost);WSACleanup();return;}}Sleep(100);printf("\n%s", buf);//break;}
}int main()
{WSADATA wsd;SOCKET sHost;SOCKADDR_IN servAddr;//服务器地址int retVal;//调用Socket函数的返回值char buf[BUF_SIZE];//初始化Socket环境if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0){printf("WSAStartup failed!\n");return -1;}sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//设置服务器Socket地址servAddr.sin_family = AF_INET;servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//在实际应用中,建议将服务器的IP地址和端口号保存在配置文件中servAddr.sin_port = htons(6000);//计算地址的长度int sServerAddlen = sizeof(servAddr);//调用ioctlsocket()将其设置为非阻塞模式int iMode = 1;retVal = ioctlsocket(sHost, FIONBIO, (u_long FAR*) & iMode);if (retVal == SOCKET_ERROR){printf("ioctlsocket failed!");WSACleanup();return -1;}//循环等待while (true){//连接到服务器retVal = connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr));if (SOCKET_ERROR == retVal){int err = WSAGetLastError();//无法立即完成非阻塞Socket上的操作if (err == WSAEWOULDBLOCK || err == WSAEINVAL){Sleep(1);printf("check connect!\n");continue;}else if (err == WSAEISCONN)//已建立连接{break;}else{printf("connection failed!\n");closesocket(sHost);WSACleanup();return -1;}}}unsigned long threadId = _beginthread(recv, 0, &sHost);//启动一个线程接收数据的线程 while (true){//向服务器发送字符串,并显示反馈信息printf("input a string to send:\n");std::string str;//接收输入的数据std::cin >> str;//将用户输入的数据复制到buf中ZeroMemory(buf, BUF_SIZE);strcpy_s(buf, str.c_str());if (strcmp(buf, "quit") == 0){printf("quit!\n");break;}while (true){retVal = send(sHost, buf, strlen(buf), 0);if (SOCKET_ERROR == retVal){int err = WSAGetLastError();if (err == WSAEWOULDBLOCK){//无法立即完成非阻塞Socket上的操作Sleep(5);continue;}else{printf("send failed!\n");closesocket(sHost);WSACleanup();return -1;}}break;}}return 0;
}
监听状态:

收到客户端消息:

参考书籍:《Visual C++2017 网络编程实战》
相关文章:
【网络编程】WSAAsyncSelect 模型
十、基于I/O模型的网络开发 接着上次的博客继续分享:select模型 10.8 异步选择模型WSAAsyncSelect 10.8.1 基本概念 WSAAsyncSelect模型是Windows socket的一个异步I/O 模型,利用这个模型,应用程序 可在一个套接字上接收以Windows 消息为基…...
视觉-语言模型-出发点CLIP--(精读论文)
阅读建议:配合这个源码分析阅读效果更加 研究背景和目的 介绍当前计算机视觉系统依赖固定类别标签训练的局限性,以及自然语言监督作为一种有潜力替代方式的研究现状。强调论文旨在探索从自然语言监督中学习可迁移视觉模型,实现零样本学习&a…...
docker本地部署RagFlow
1.安装 克隆仓库 git clone https://github.com/infiniflow/ragflow.git构建预建的Docker映像并启动服务器 cd ragflow/docker chmod x ./entrypoint.sh docker compose -f docker-compose.yml -p ragflow up -d修改ragflow/docker/.env文件 #RAGFLOW_IMAGEinfiniflow/ragfl…...
机器学习数学基础:44.多元线性回归
一、文字内容详解 1. 多重共线性的判断——皮尔逊相关系数 皮尔逊相关系数用于衡量自变量间的线性相关程度,取值范围为 ([-1, 1]): 绝对值越接近 (1),变量间线性相关性越强;越接近 (0),相关性越弱。在多重共线性判断…...
GetWindowLongPtr函数分析
第一部分: #ifdef UNICODE FUNCLOG2(LOG_GENERAL, LONG_PTR, APIENTRY, GetWindowLongPtrW, HWND, hwnd, int, nIndex) #else FUNCLOG2(LOG_GENERAL, LONG_PTR, APIENTRY, GetWindowLongPtrA, HWND, hwnd, int, nIndex) #endif // UNICODE LONG_PTR APIENTRY GetWin…...
大语言模型(LLM)和嵌入模型的统一调用接口
ChatModelFactory、EmbeddingModelFactory 讲解代码:import os from dotenv import load_dotenv, find_dotenv_ load_dotenv(find_dotenv())from langchain_openai import ChatOpenAI, OpenAIEmbeddings, AzureChatOpenAI, AzureOpenAIEmbeddingsclass ChatModelF…...
大白话html语义化标签优势与应用场景
大白话html语义化标签优势与应用场景 大白话解释 语义化标签就是那些名字能让人一看就大概知道它是用来做什么的标签。以前我们经常用<div>来做各种布局,但是<div>本身没有什么实际的含义,就像一个没有名字的盒子。而语义化标签就像是有名…...
Scala:在哪里写类的属性?类的属性必须私有吗?类的必须初始化吗?
哪里写类的属性 直接在类体中定义属性 class Circle {private var _radius: Double 0.0def radius: Double _radiusdef radius_(newRadius: Double): Unit {_radius newRadius}def area: Double scala.math.Pi * _radius * _radius } 可以在类体内部直接定义属性。例如&am…...
Android源码编译命令详解
一、引言 先看下面几条指令,相信编译过Android源码的人都再熟悉不过的。 source setenv.sh lunch make -j8记得最初刚接触Android时,同事告诉我用上面的指令就可以编译Android源码,指令虽短但过几天就记不全或者忘记顺序,每次编…...
任务11:路由器配置与静态路由配置
目录 一、概念 二、路由器配置 三、配置静态路由CSDN 原创主页:不羁https://blog.csdn.net/2303_76492156?typeblog 一、概念 1、路由器的作用:通过路由表进行数据的转发。 2、交换机的作用:通过学习和识别 MAC 地址,依据 M…...
Unity之如何实现哔哩哔哩直播弹幕游戏
前言 什么是直播间互动? 当我们使用哔哩哔哩进行直播或者观看视频时,我们可以通过接入哔哩哔哩提供的 直播&互动玩法SDK,让直播和视频可以与Unity3D游戏客户端或者游戏服务器进行互动。 环境要求 Unity 2020.x或更高版本 依赖库:Newtonsoft Json Unity Package 在P…...
Python实例:PyMuPDF实现PDF翻译,英文翻译为中文,并按段落创建中文PDF
基于PyMuPDF与百度翻译的PDF翻译处理系统开发:中文乱码解决方案与自动化排版实践 一 、功能预览:将英文翻译为中文后创建的PDF 二、完整代码 from reportlab.lib.pagesizes import letter from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle...
LeeCode题库第四十六题
46.全排列 项目场景: 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1: 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&am…...
LangChain4j开发RAG入门示例
本文将详细介绍如何基于Java语言,使用Langchain4j开源框架、Milvus向量数据、阿里Qwen大模型,开发一个RAG入门级简单示例。本示例虽然简单,但涉及到多个知识点,包括:Milvus初始化、Embedding模型、文档切片、Springboo…...
快速从C过度C++(一):namespace,C++的输入和输出,缺省参数,函数重载
📝前言: 本文章适合有一定C语言编程基础的读者浏览,主要介绍从C语言到C过度,我们首先要掌握的一些基础知识,以便于我们快速进入C的学习,为后面的学习打下基础。 这篇文章的主要内容有: 1&#x…...
课程《Deep Learning Specialization》
在coursera上,Deep Learning Specialization 课程内容如下图所示:...
微服务与消息队列RabbitMQ
简介 同步模式 异步模式 内容 解决方案RabbitMQ 同步调用的优缺点 同步调用的优势是什么? 时效性强,等待到结果后才返回。 同步调用的问题是什么? 拓展性差性能下降级联失败问题...
苹果 M3 Ultra 芯片深度解析:AI 时代的性能革命
2025 年 3 月 5 日,苹果正式发布了其史上最强 PC 芯片 ——M3 Ultra。这款基于 UltraFusion 封装技术的旗舰级 SoC,不仅延续了苹果芯片在能效比上的传统优势,更通过架构创新与硬件升级,将 AI 计算能力推向了新高度。本文将从性能突…...
通义千问:Qwen2.5-0.5B模型架构解释
通义千问:Qwen2.5-0.5B模型架构解释 1. 模型权重文件 .mdl、.msc:存储模型核心参数,是模型训练后学习到的知识载体,包含神经网络各层权重,加载后模型才能执行推理、生成等任务。 .mdl文件:通常是模型的核心权重数据文件,存储神经网络各层的权重参数、张量等关键数据,是…...
安装完flash-attn,使用时报错undefined symbol
去flash attention官网下载安装包, 注意需要根据自己的torch版本,cuda版本(可以选择低于自己cuda版本的) 和python版本进行选择。 如果whl文件名上包含参数abiTRUE,则会报错。需要安装包含abiFALSE的whl文件。 卸载:卸载原先报错的flash-attn pip uni…...
【Linux】冯诺依曼体系与操作系统理解
🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:Linux 目录 前言 一、冯诺依曼体系结构 二、操作系统 1. 操作系统的概念 2. 操作系统存在的意义 3. 操作系统的管理方式 4. 补充:理解系统调用…...
玩转ChatGPT:GPT 深入研究功能
一、写在前面 民间总结: 理科看Claude 3.7 Sonnet 文科看DeepSeek-R1 那么,ChatGPT呢? 看Deep Research(深入研究)功能。 对于科研狗来说,在这个文章爆炸的时代,如何利用AI准确、高效地收…...
虚函数和虚表的原理是什么?
虚函数是一个使用virtual关键字声明的成员函数,在基类中声明虚函数,在子类中可以使用override重写该函数。虚函数根据指针或引用指向的实际对象调用,实现运行时的多态。 虚函数表(虚表)是一个用于存储虚函数地址的数组…...
laravel es 相关代码 ElasticSearch
来源: github <?phpnamespace App\Http\Controllers;use Elastic\Elasticsearch\ClientBuilder; use Illuminate\Support\Facades\DB;class ElasticSearch extends Controller {public $client null;public function __construct(){$this->client ClientB…...
字节跳动C++客户端开发实习生内推-抖音基础技术
智能手机爱好者和使用者,追求良好的用户体验; 具有良好的编程习惯,代码结构清晰,命名规范; 熟练掌握数据结构与算法、计算机网络、操作系统、编译原理等课程; 熟练掌握C/C/OC/Swift一种或多种语言ÿ…...
C语言_数据结构总结6:链式栈
纯c语言代码,不涉及C 顺序栈的实现,欢迎查看这篇文章:C语言_数据结构总结5:顺序栈-CSDN博客 0. 结构单元 #include<stdio.h> #include<stdlib.h> typedef int ElemType; typedef struct Linknode { ElemType…...
DQN(Deep Q - Network)原理举例说明
DQN(Deep Q - Network)原理举例说明 1. 基本概念回顾 DQN 结合了深度学习和 Q - learning 算法,用深度神经网络来近似 Q 值函数,解决传统 Q - learning 在处理高维状态空间时的局限性。Q 值表示在某个状态下采取某个动作所能获得的期望累积奖励。 以下是DQN和A3C的原理对…...
物联网-IoTivity:开源的物联网框架
IoTivity 是一个开源的物联网(IoT)框架,旨在为物联网设备提供互操作性、安全性和可扩展性。它由 Open Connectivity Foundation (OCF) 主导开发,遵循 OCF 的标准,致力于实现设备之间的无缝连接和通信。IoTivity 提供了一个统一的框架,支持设备发现、数据交换、设备管理和…...
基于DeepSeek的智慧医药系统(源码+部署教程)
运行环境 智慧医药系统运行环境如下: 前端: HTMLCSS后端:Java AIGCDeepseekIDE工具:IDEA技术栈:Springboot HTMLCSS MySQL 主要角色 智慧医药系统主要分为两个角色。 游客 尚未进行注册和登录。具备登录注册、…...
基于Linux系统的边缘智能终端(RK3568+EtherCAT+PCIe+4G+5G)
背景 现有产品基本都是传统的产品,比如之前写的RTU还有基于Linux系统的物联网采集终端都是传统意义的产品,大家做的都差不多,能拼的除了价格之外就是软硬件的基本功了,好的产品肯定是要经过时间的磨合的。没有任何人可以写出来没有…...
