frameworks 之Socket
frameworks 之Socket
- Socket
- 服务端
- 1.创建Socket。
- 2.绑定socket
- 3.监听socket
- 4.等待客户端连接
- 5.读取或者写入给客户端
- 客户端
- 1.创建Socket。
- 2.连接服务端Socket
- 3.读取或者写入给客户端
- 4.关闭socket
- 演示代码
- Epoll
- 创建Epoll
- 添加或删除Epoll
- 等待消息返回Epoll
- 演示代码
- SocketPair
- 创建socketPair
- 设置对应的属性
- 演示代码
Socket是应用层与TCP/IP协议族通信的中间软件抽象层。他作为Android 进程间的通信。
涉及到的类如下
- frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
Socket
创建一个socket 需要几个步骤
服务端: socket -> bind -> listen -> accept -> read/write -> close
客户端: socket -> connect -> read/write -> close
服务端
1.创建Socket。
第一个参数为协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL**(或称AF_UNIX,Unix域socket,这个是我们的讲解重点)**、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址
第二个参数 指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET
第三个参数为 指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
int socketFd = socket(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL);
2.绑定socket
bind()函数就是将给这个描述字绑定一个名字。addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同。addrlen:对应的是地址的长度。
int bindResult = bind(socketFd, (struct sockaddr *)&serviceAddr, serviceLen);
地址为抽象和文件类型。文件类型会生成一个文件在本地,抽象需要在地址前面加0,对应会生成@开头。可以用如下命令查询查看
netstat -an | grep 地址名称
3.监听socket
设置监听的最大连接个数
int listenerResult = listen(socketFd, SOCKET_NUMBER);
4.等待客户端连接
传入客户端的对象 和长度 由内核写入。等待客户端的连接。
int connectFd = accept(socketFd, (struct sockaddr *)&clientAddr, &clintLen);
5.读取或者写入给客户端
通过 read 或者 write 函数跟客户端通信
int dataSize = read(connectFd, &buffer, sizeof(buffer));if (dataSize == 0){printf("客户端关闭连接\n");} else if (dataSize == -1){printf("读取异常\n");exit(1);} else {printf("客户端发送了: %s\n" ,buffer);for (int i = 0; i < sizeof(buffer); i++){buffer[i] = toupper(buffer[i]);}write(connectFd, buffer, sizeof(buffer));}
客户端
1.创建Socket。
int serviceFd = socket(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL);
2.连接服务端Socket
发起对服务端的连接,连接成功后 服务端 accept 方法将继续执行
int connectResult = connect(serviceFd, (struct sockaddr *)&clientAddr, clientLen);
3.读取或者写入给客户端
int wirteResult = write(serviceFd, winBuffer, sizeof(winBuffer));printf("写入服务端数据 %i", wirteResult);// 阻塞读取服务端数据int readResult =read(serviceFd, winBuffer, sizeof(winBuffer));
4.关闭socket
close(serviceFd);
演示代码
服务端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// scoket相关
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>// 协议域
int SOCKET_DOMIAN = AF_UNIX;
// 类型
int SOCKET_TYPE = SOCK_STREAM;
// 协议,常用tcp udp
int SOCKET_PROTOCOL = 0;
// SOCKETD地址
#define SOCKET_SERVICE_ADDRESS "natvie_socket_test"
// 允许连接的长度
#define SOCKET_NUMBER 20
// 读取数据大小
#define BUFFER_SZIE 80/*** 主文件入口
*/
int main (void) {// socket 文件描述符int socketFd;// 客户端的socket 文件描述符int clintSocetFd;// socket 实体类struct sockaddr_un serviceAddr, clientAddr;// 地址长度socklen_t serviceLen; socklen_t clintLen;// 数据读取char buffer[BUFFER_SZIE];// 创建socketsocketFd = socket(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL);if (socketFd == -1){printf("创建 socket 失败\n");exit(1);}// 清空memset(&serviceAddr, 0 ,sizeof(sockaddr_un));serviceAddr.sun_family = AF_UNIX;// 设置地址strncpy(serviceAddr.sun_path, SOCKET_SERVICE_ADDRESS, sizeof(serviceAddr.sun_path) - 1);// 计算长度serviceLen = sizeof(serviceAddr.sun_family) + sizeof(serviceAddr.sun_path);// 绑定地址int bindResult = bind(socketFd, (struct sockaddr *)&serviceAddr, serviceLen);if (bindResult == -1){printf("绑定 socket 失败\n");exit(1);}// 绑定成功后 需要监听int listenerResult = listen(socketFd, SOCKET_NUMBER);if (listenerResult == -1){printf("监听 socket 失败\n");exit(1);}printf("服务端 socket建立 等待连接\n");// 死循环等待连接while (1){// 等待接收客户端连接, 同时客户端的信息会写入该类, 会阻塞在这里clintLen = sizeof(struct sockaddr_un);int connectFd = accept(socketFd, (struct sockaddr *)&clientAddr, &clintLen);if (connectFd == -1) {printf("监听 socket 失败\n");exit(1);}// 创建成功,循环读取消息while (1){// 0 为关闭 -1 为异常int dataSize = read(connectFd, &buffer, sizeof(buffer));if (dataSize == 0){printf("客户端关闭连接\n");} else if (dataSize == -1){printf("读取异常\n");exit(1);} else {printf("客户端发送了: %s\n" ,buffer);for (int i = 0; i < sizeof(buffer); i++){buffer[i] = toupper(buffer[i]);}write(connectFd, buffer, sizeof(buffer));}}}// 退出for循环 关闭socketprintf("服务端关闭连接\n");close(socketFd);return 0;
}
客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// scoket相关
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>// 协议域
int SOCKET_DOMIAN = AF_UNIX;
// 类型
int SOCKET_TYPE = SOCK_STREAM;
// 协议,常用tcp udp
int SOCKET_PROTOCOL = 0;
// SOCKETD地址
#define SOCKET_SERVICE_ADDRESS "natvie_socket_test"
// 允许连接的长度
#define SOCKET_NUMBER 20
// 读取数据大小
#define BUFFER_SZIE 80
// 输入最大行
#define MAXLINE 80int main(void) {// 客户端操作符int serviceFd;sockaddr_un clientAddr;// 地址长度socklen_t clientLen;// 从输入框输入流char winBuffer[BUFFER_SZIE];serviceFd = socket(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL);if (serviceFd == -1){printf("创建 socket 失败");exit(0);}// 清空数据memset(&clientAddr, 0, sizeof(struct sockaddr_un));// 赋值地址clientAddr.sun_family = AF_UNIX;strncpy(clientAddr.sun_path, SOCKET_SERVICE_ADDRESS, sizeof(clientAddr.sun_path) - 1);clientLen = sizeof(clientAddr);printf("socket地址: %s\n", clientAddr.sun_path);int connectResult = connect(serviceFd, (struct sockaddr *)&clientAddr, clientLen);if (connectResult == -1){perror("连接 socket 失败");exit(0);}printf("请输入对应的数据:");while (fgets(winBuffer, MAXLINE, stdin)){// 把读到的数据给服务端int wirteResult = write(serviceFd, winBuffer, sizeof(winBuffer));printf("写入服务端数据 %i", wirteResult);// 阻塞读取服务端数据int readResult =read(serviceFd, winBuffer, sizeof(winBuffer));if (readResult <= 0) { printf("服务端异常或者已关闭\n");break;}else { printf("接收到服务端的消息: %s \n",winBuffer);}printf("请输入对应的数据:");}close(serviceFd);return 0;
}
Epoll
上面提到的socket 的 accept 和 read 等方法都是阻塞方法,等多客户端无法实现实时的读取和监听,如果每个客户端开对应的线程则比较耗资源。因此有了Epoll 等待唤醒。Epoll 有如下方法。
创建Epoll
需要传入一个数量,该数量大于0即可。并会返回一个文件描述符
// 创建 epoll, 参数size 实际没作用,但是要大于0
int epollFd = epoll_create(EPOLL_SZIE);
添加或删除Epoll
第二参数控制 添加还是删除
第三个参数为需要监听的文件操作符
第四个参数为 epoll_event 类型
data.fd 可以存储对应的文件ID
events属性表示数据类型 EPOLLIN
int addResult = epoll_ctl(epollFd, EPOLL_CTL_ADD, serviceFd, &epollEvent);
等待消息返回Epoll
events参数传入事件数组,内核会对应写入的数组。可通过 events.data.fd 获取对应的客户端。
size 表示每次可以处理的最大事件数量
最后参数代表等待的事件,0为马上返回,-1为阻塞等待。
int eventNum = epoll_wait(epollFd, events, EPOLL_EVENT_MAX_SZIE, EPOLL_TIEM_OUT);
演示代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// scoket相关
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
// epoll 相关
#include <sys/epoll.h>// 协议域
int SOCKET_DOMIAN = AF_UNIX;
// 类型
int SOCKET_TYPE = SOCK_STREAM;
// 协议,常用tcp udp
int SOCKET_PROTOCOL = 0;
// SOCKETD地址
#define SOCKET_SERVICE_ADDRESS "epoll_socket_test"
// 允许连接的长度
#define SOCKET_NUMBER 20
// 读取数据大小
#define BUFFER_SZIE 80
// epoll大小
#define EPOLL_SZIE 80
// epoll消息大小
#define EPOLL_EVENT_MAX_SZIE 20
// epoll消息超时
#define EPOLL_TIEM_OUT -1// 采用抽象作用域
int main(void) {int serviceFd;sockaddr_un serviceAddr;socklen_t serviceLen, clientLen;char buffer[BUFFER_SZIE];serviceFd = socket(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL);if (serviceFd == -1) {perror("创建 socket 失败");exit(0);}memset(&serviceAddr, 0 , sizeof(struct sockaddr) - 1);serviceAddr.sun_family = AF_UNIX;// 这里采用抽象的协议, 第一位要给0serviceAddr.sun_path[0] = 0;strcpy(serviceAddr.sun_path + 1, SOCKET_SERVICE_ADDRESS);// serviceLen = sizeof(serviceAddr.sun_family) + strlen(SOCKET_SERVICE_ADDRESS) + 1;serviceLen = sizeof(serviceAddr.sun_family) + sizeof(serviceAddr.sun_path);printf("绑定的地址为:%s \n", serviceAddr.sun_path);// 绑定int bindResult = bind(serviceFd, (struct sockaddr *)&serviceAddr, serviceLen);if (bindResult == -1) {perror("绑定 socket 失败");exit(0);}int listenResult = listen(serviceFd, SOCKET_NUMBER);if (listenResult == -1) {perror("监听 socket 失败");exit(0);}// 创建 epoll, 参数size 实际没作用,但是要大于0 int epollFd = epoll_create(EPOLL_SZIE);if (epollFd == -1){perror("创建 epoll 失败");exit(0);}// 将对应的文件夹 添加 epoll中epoll_event epollEvent;/* *** 注意****epoll_data 是一个联合体结构成员,所有的成员公用一段内存,因此实际上只能保留一个成员它只会保存最后一个被赋值的成员,所以不要data.fd,data.ptr都赋值*/epollEvent.data.fd = serviceFd;epollEvent.events = EPOLLIN;// 循环检测 委托内核去处理// 当内核检测到事件到来时会将事件写到这个结构体数组里struct epoll_event events[EPOLL_EVENT_MAX_SZIE];int addResult = epoll_ctl(epollFd, EPOLL_CTL_ADD, serviceFd, &epollEvent); if (addResult == -1){perror("添加到 epoll 失败");exit(0);}printf("开始接收消息\n");while (1){// 等待有没消息返回// tiemOut 为0 马上返回 为-1 代表阻塞// maxevents:表示每次能处理的最大事件数,告之内核这个events有多大;这个maxevents的值不能大于创建epoll_create()时的size;int eventNum = epoll_wait(epollFd, events, EPOLL_EVENT_MAX_SZIE, EPOLL_TIEM_OUT);printf("收到消息数量: %i \n", eventNum);for (int i = 0; i < eventNum; i++){// 有连接请求到来,走到这里if (events[i].data.fd == serviceFd){// 客户端信息填充struct sockaddr_un clientAddr;socklen_t clientLen = sizeof(clientAddr);int connectFd = accept(serviceFd, (struct sockaddr *)&clientAddr, &clientLen);if (connectFd == -1){perror("接收客户端失败");exit(0);}printf("接收到新的客户端\n");//将用于通信的文件描述符挂到epoll树上epollEvent.data.fd = connectFd;epollEvent.events = EPOLLIN;epoll_ctl(epollFd, EPOLL_CTL_ADD, connectFd, &epollEvent);} else{// 其他的为客户端发送的值// 通信也有可能是写事件if (events[i].events & EPOLLOUT){//这里先忽略写事件continue;}char buf[1024]={0};int count = read(events[i].data.fd, buf, sizeof(buf));if (count == 0){// 关闭了客户端要关闭printf("收到客户端关闭");close(events[i].data.fd);epoll_ctl(epollFd, EPOLL_CTL_DEL, events[i].data.fd, NULL);continue;}if (count == -1){perror("接收消息异常退出");exit(0);}printf("收到了消息事件:%s \n", buf);for (int i = 0; i < sizeof(buf); i++){buf[i] = toupper(buf[i]);}write(events[i].data.fd, buf, sizeof(buf));}}}close(serviceFd);return 0;
}
SocketPair
如果是单纯1对1通讯,可通过 socketPair 快速建立服务端和客户端
创建socketPair
创建一个数组存储对应的ID,创建的socket 会放在该数组里面
int socketFds[2];
// 创建socke 第一个作为服务端 第二个作为客户端
int result = socketpair(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL, socketFds);
设置对应的属性
以下代码设置对应的缓冲区
socklen_t len = sizeof(BUFFER_SZIE);
setsockopt(socketFds[0], SOL_SOCKET, SO_SNDBUF, &BUFFER_SZIE, len);
setsockopt(socketFds[0], SOL_SOCKET, SO_RCVBUF, &BUFFER_SZIE, len);
setsockopt(socketFds[1], SOL_SOCKET, SO_SNDBUF, &BUFFER_SZIE, len);
setsockopt(socketFds[1], SOL_SOCKET, SO_RCVBUF, &BUFFER_SZIE, len);
演示代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <sys/types.h>
#include <sys/socket.h>#include <unistd.h>// 协议域
int SOCKET_DOMIAN = AF_UNIX;
// 类型
int SOCKET_TYPE = SOCK_STREAM;
// 协议,常用tcp udp
int SOCKET_PROTOCOL = 0;
// 缓存区大小
int BUFFER_SZIE = 1024;int main(void) {int socketFds[2];// 创建socke 第一个作为服务端 第二个作为客户端int result = socketpair(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL, socketFds);if (result == -1){perror("创建 socketPair 错误");exit(0);}/*** 第一个参数socket是套接字描述符。* 第二个参数level是被设置的选项的级别,如果想要在套接字级别上设置选项,就必须把level设置为 SOL_SOCKET。* option_name指定准备设置的选项,option_name可以有哪些取值,这取决于level,在套接字级别上(SOL_SOCKET)* 主要设置缓存区大小*/socklen_t len = sizeof(BUFFER_SZIE);setsockopt(socketFds[0], SOL_SOCKET, SO_SNDBUF, &BUFFER_SZIE, len);setsockopt(socketFds[0], SOL_SOCKET, SO_RCVBUF, &BUFFER_SZIE, len);setsockopt(socketFds[1], SOL_SOCKET, SO_SNDBUF, &BUFFER_SZIE, len);setsockopt(socketFds[1], SOL_SOCKET, SO_RCVBUF, &BUFFER_SZIE, len);int pid = fork();printf("孵化出来的进程号为 %i \n", pid);// 在子进程为0if (!pid){printf("执行子进程\n");// 为子进程close(socketFds[0]);int count = 0;while (1){// 休眠一秒sleep(1);// 发送给服务端端write(socketFds[1], &count, sizeof(count));int size = read(socketFds[1], &count, sizeof(count));printf("收到服务端数据 %i \n", count);++count;}} else {printf("执行父进程\n");// 为父进程close(socketFds[1]);int count = 0;while (1){ // 读取客户端数据int size = read(socketFds[0], &count, sizeof(count));if (read <= 0){perror("客户端异常退出 \n");exit(0);}printf("收到客户端数据 %i \n", count);++count;// 发送给客户端write(socketFds[0], &count, sizeof(count));}}
}
相关文章:
frameworks 之Socket
frameworks 之Socket Socket服务端1.创建Socket。2.绑定socket3.监听socket4.等待客户端连接5.读取或者写入给客户端 客户端1.创建Socket。2.连接服务端Socket3.读取或者写入给客户端4.关闭socket 演示代码 Epoll创建Epoll添加或删除Epoll等待消息返回Epoll演示代码 SocketPair…...
WEB前端开发中如何实现大文件上传?
大文件上传是个非常普遍的场景,在面试中也会经常被问到,大文件上传的实现思路和流程。在日常开发中,无论是云存储、视频分享平台还是企业级应用,大文件上传都是用户与服务器之间交互的重要环节。随着现代网络应用的日益复杂化&…...
ts给vue中props设置指定类型
interface IBaseObject {[key: string | number]: any; }export default defineComponent({name:xx,props:{data:{type:Object as PropType<IBaseObject>,default:()>({}),required:true},}, })...
模拟实现c++中的list模版
☺☺☺☺☺☺☺☺☺☺ 点击 进入杀马特的主页☺☺☺☺☺☺☺☺☺☺ 目录 一list简述: 二库内常用接口函数使用: 1reverse(): 2.s…...
从信息论的角度看微博推荐算法
引言 在数字时代,推荐系统已成为社交媒体和其他在线服务平台的核心组成部分。它们通过分析用户行为和偏好,为用户提供个性化的内容,从而提高用户满意度和平台的参与度。推荐系统不仅能够增强用户体验,还能显著提升广告投放的效率…...
CISC(复杂指令集)与RISC(精简指令集)的区别
RISC(Reduced Instruction Set Computer)和CISC(complex instruction set computer)是当前CPU的两种架构。 它们的区别在于不同的CPU设计理念和方法。 早期的CPU全部是CISC架构,它的设计目的是要用最少的机器语言指令来完成所需的计算任务。比如对于乘法运算&#x…...
自定义数据库连接的艺术:Laravel中配置多数据库连接详解
自定义数据库连接的艺术:Laravel中配置多数据库连接详解 在现代Web应用开发中,经常需要连接到多个数据库。Laravel,作为PHP界最受欢迎的框架之一,提供了强大的数据库抽象层,支持多种数据库系统,并且允许开…...
力扣高频SQL 50题(基础版)第八题
文章目录 力扣高频SQL 50题(基础版)第八题1581. 进店却未进行过交易的顾客题目说明思路分析实现过程准备数据:实现方式:结果截图:总结: 力扣高频SQL 50题(基础版)第八题 1581. 进店…...
【C++20】从0开始自制协程库
文章目录 参考 很多人对协程的理解就是在用户态线程把CPU对线程的调度复制了一遍,减少了线程的数量,也就是说在一个线程内完成对协程的调度,不需要线程切换导致上下文切换的开销。但是线程切换是CPU行为,就算你的程序只有一个线程…...
Docker 深度解析:从入门到精通
引言 在当今的软件开发领域,容器化技术已经成为一种趋势。Docker 作为容器化技术的代表,以其轻量级、可移植性和易用性,被广泛应用于各种场景。本文将从 Docker 的基本概念入手,详细介绍 Docker 的安装、基本操作、网络配置、数据…...
[C++] 模板编程-02 类模板
一 类模板 template <class T或者typename T> class 类名 { .......... } 1.1 两种不同的实现 在以下的两种实现中,其实第一种叫做成员函数模板,并不能称为类模板因为这种实现,我们在调用时,并不需要实例化为Product这个类指定指定特定类型。 // 实现1 clas…...
嵌入式C++、STM32、树莓派4B、OpenCV、TensorFlow/Keras深度学习:基于边缘计算的实时异常行为识别
1. 项目概述 随着物联网和人工智能技术的发展,智能家居安全系统越来越受到人们的关注。本项目旨在设计并实现一套基于边缘计算的智能家居安全系统,利用STM32微控制器和树莓派等边缘设备,实时分析摄像头数据,识别异常行为(如入侵、跌倒等),并及时发出警报,提高家庭安全性。 系…...
C++ //练习 15.30 编写你自己的Basket类,用它计算上一个练习中交易记录的总价格。
C Primer(第5版) 练习 15.30 练习 15.30 编写你自己的Basket类,用它计算上一个练习中交易记录的总价格。 环境:Linux Ubuntu(云服务器) 工具:vim 代码块: /********************…...
3个方法快速找回忘记的PDF文件密码
为确保PDF文件的重要信息不轻易外泄,很多人都会给PDF文件设置打开密码,但伴随着时间的推移,让我们忘记了原本设置的密码,但这时,我们又非常急需要打开编辑这份文件,这时我们该怎么办呢?下面小编…...
排序算法:选择排序,golang实现
目录 前言 选择排序 代码示例 1. 算法包 2. 选择排序代码 3. 模拟排序 4. 运行程序 5. 从大到小排序 循环细节 外层循环 内层循环 总结 选择排序的适用场景 1. 数据规模非常小 2. 稳定性不重要 3. 几乎全部数据已排序 4. 教育目的 前言 在实际场景中…...
【测试】博客系统的测试报告
项目背景 个人博客系统采用了 SSM 框架与 Redis 缓存技术的组合 ,为用户提供了一个功能丰富、性能优越的博客平台。 在技术架构上 ,SSM 框架确保了系统的稳定性和可扩展性。Spring 负责管理项目的各种组件 ,Spring MVC 实现了清晰的请求处理…...
PointCLIP: Point Cloud Understanding by CLIP
Abstract 近年来,基于对比视觉语言预训练(CLIP)的零镜头和少镜头学习在二维视觉识别中表现出了令人鼓舞的效果,该方法在开放词汇设置下学习图像与相应文本的匹配。然而,通过大规模二维图像-文本对预训练的CLIP是否可以推广到三维识别&#x…...
搜索(剪枝)
定义: 剪枝,就是减少搜索树的规模、尽早排除搜索树中不必要分支的一种手段。 在深度优先搜索中,有以下几类常见的剪枝方法: 优化搜索顺序排除等效冗余可行性剪枝最优性剪枝记忆化剪枝 例题1:AcWing 167.木棒 题目:…...
python基础知识点
最近系统温习了一遍python基础语法,把自己不熟知的知识点罗列一遍,便于查阅~~ python教程 Python 基础教程 | 菜鸟教程 1、python标识符 以单下划线开头 _foo 的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用 f…...
Android SurfaceFlinger——GraphicBuffer获取内存信息(三十一)
上一篇文章介绍了 GraphicBuffer 初始化的 initWithSize() 函数中的申请内存流程,这里我们看一下另一个比较重要的函数,GraphicBufferMapper. getTransportSize 获取内存信息。该函数通常在需要了解缓冲区的实际内存占用情况时调用,例如在调试内存使用情况或优化性能时。 一…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
