[错误经验 坑]关于UDP服务器和客户端通信使用的recvfrom的输出型参数len没有被初始化导致的问题
[错误经验 坑]关于UDP服务器和客户端通信使用的recvfrom的输出型参数len没有被初始化导致的问题
@水墨不写bug
文章目录
- 一、困惑:
- 二、解答:
- (1)函数原型
- 1. `int sockfd`
- 2. `void *buf`
- 3. `size_t len`
- 4. `int flags`
- 5. `struct sockaddr *src_addr`
- 6. `socklen_t *addrlen`
- (2)返回值
- 三、考虑如下情景:(一套用于通信的UDP服务端和客户端)
- 问题所在
- 四、结论:
一、困惑:
看到标题,你一定很困惑,输出型参数?为什么需要初始化?
二、解答:
Linux下搭建UDP通信的时候,会用到recvfrom函数,函数原型如下:
#include <sys/socket.h>ssize_t recvfrom(int sockfd, // 套接字文件描述符void *buf, // 接收数据的缓冲区size_t len, // 缓冲区的最大容量int flags, // 控制接收行为的标志位struct sockaddr *src_addr, // 发送方的地址信息(输出参数)socklen_t *addrlen // 地址结构体的长度(输入/输出参数)
);
recvfrom
是 Linux 网络编程中用于 接收数据报 的核心系统调用,常用于无连接的套接字(如 UDP)。它不仅能接收数据,还能获取发送方的地址信息。以下是其函数原型及各参数的详细说明:
(1)函数原型
#include <sys/socket.h>ssize_t recvfrom(int sockfd, // 套接字文件描述符void *buf, // 接收数据的缓冲区size_t len, // 缓冲区的最大容量int flags, // 控制接收行为的标志位struct sockaddr *src_addr, // 发送方的地址信息(输出参数)socklen_t *addrlen // 地址结构体的长度(输入/输出参数)
);
1. int sockfd
- 作用:已创建的套接字文件描述符。
- 要求:
- 必须为 无连接协议(如 UDP)的套接字,或未调用
connect
的面向连接协议套接字。 - 若套接字已通过
connect
建立连接(如 TCP),应使用recv
而非recvfrom
。
- 必须为 无连接协议(如 UDP)的套接字,或未调用
2. void *buf
- 作用:指向接收数据的缓冲区。
- 要求:
- 缓冲区必须由用户预先分配内存,大小至少为
len
字节。 - 数据以二进制形式存储,需根据协议自行解析。
- 缓冲区必须由用户预先分配内存,大小至少为
3. size_t len
- 作用:缓冲区
buf
的最大容量。 - 要求:
- 必须小于或等于缓冲区的实际大小,否则可能引发缓冲区溢出。
- 若数据长度超过
len
,多余部分会被丢弃(UDP 下)。
4. int flags
- 作用:控制接收行为的标志位,多个标志可通过
|
组合。 - 常见标志:
标志 说明 MSG_WAITALL
阻塞直到请求的 len
字节全部接收完成(通常用于流式协议如 TCP)MSG_DONTWAIT
非阻塞模式:若无数据可读,立即返回 EAGAIN
或EWOULDBLOCK
MSG_PEEK
窥视数据但不从内核缓冲区移除(下次调用仍可读到相同数据) MSG_TRUNC
若数据超过 len
,返回实际数据长度(需检查返回值是否大于len
)
5. struct sockaddr *src_addr
- 作用:输出参数,保存发送方的地址信息(如 IP 和端口)。
- 要求:
- 若无需获取发送方地址,可设为
NULL
(此时addrlen
也应为NULL
)。 - 需预先分配足够大的内存(如
struct sockaddr_in
或struct sockaddr_in6
)。
- 若无需获取发送方地址,可设为
6. socklen_t *addrlen
- 作用:
- 输入:指定
src_addr
缓冲区的最大容量。 - 输出:实际写入的地址结构体大小。
- 输入:指定
- 要求:
- 必须初始化为
src_addr
缓冲区的实际大小(如sizeof(struct sockaddr_in)
)。 - 若实际地址长度超过
*addrlen
,地址会被截断(可通过返回值检查)。
- 必须初始化为
(2)返回值
- 成功:返回接收到的字节数(
>=0
)。 - 失败:返回
-1
,错误码存储在errno
中。 - 特殊场景:
- UDP 数据报长度超过
len
:返回实际接收的字节数(可能小于原始长度),需检查flags
是否包含MSG_TRUNC
。 - 对端关闭连接(TCP):返回
0
(需结合协议逻辑处理)。
- UDP 数据报长度超过
三、考虑如下情景:(一套用于通信的UDP服务端和客户端)
//udp服务器#include <iostream>
#include <string>
#include <cstring>#include <cassert>#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>int main()
{//1.创建套接字socket fd,并且填充结构体信息int udpsockfd = socket(AF_INET,SOCK_DGRAM,0);if(udpsockfd < 0){perror("create sockfd failed!");assert(false); }std::cout<<"create success!\n"<<std::endl;struct sockaddr_in self;bzero(&self,sizeof(self));self.sin_family = AF_INET;self.sin_port = htons(8888);//暂时硬编码self.sin_addr.s_addr = INADDR_ANY;//2.绑定:设置进内核int res = ::bind(udpsockfd,(struct sockaddr*)&self,sizeof(self));if(res < 0){perror("socket bind fail!");assert(false);}std::cout<<"bind success!\n"<<std::endl;//3.收发信息//服务器首先是收到信息,并且获得发送信息的客户端的sockaddr信息//然后才能往客户端发送信息while(true){struct sockaddr_in client;socklen_t len = sizeof(client);///事先初始化为sizeof clientstd::cout<<"----"<<std::endl<<len<<std::endl<<"----"<<std::endl;char buf[1024] = {0};ssize_t n = recvfrom(udpsockfd,buf,sizeof(buf) - 1,0,(struct sockaddr*)&client,&len);std::cout<<"----"<<std::endl<<len<<std::endl<<"----"<<std::endl;//在这里就获取到了客户端sockaddr结构体信息了if(n < 0){perror("recvfrom fail\n");assert(false);}else{buf[n] = 0;std::cout<<"GetFromClient: "<<buf<<std::endl;const char* buf = "hello client!\n";ssize_t m = sendto(udpsockfd,buf,strlen(buf),0,(struct sockaddr*)&client,len);if(m < 0){perror("sendto fail!\n");assert(false);}}sleep(1);}return 0;
}
//udp客户端
#include <iostream>
#include <string>
#include <cstring>#include <cassert>#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
int main()
{//1.创建套接字socket fd,并且填充结构体信息int udpsockfd = socket(AF_INET,SOCK_DGRAM,0);if(udpsockfd < 0){perror("create sockfd failed!");assert(false); }std::cout<<"create success!\n"<<std::endl;//客户端不需要bind,OS自动绑定随机端口//2.填充server信息,在后面send的时候需要用到server信息struct sockaddr_in server;bzero(&server,sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(8888); //这里暂时先硬编码server.sin_addr.s_addr = inet_addr("127.0.0.1");//3.收发数据while(true){std::string inbuf = "I am client,hello server!";ssize_t n = sendto(udpsockfd,inbuf.c_str(),inbuf.size(),0,(struct sockaddr*)&server,sizeof(server));if(n < 0){perror("sendto fail!");assert(false);}else{char buf[1024] = {0};struct sockaddr_in tem;socklen_t len = sizeof(tem);/事先初始化为sizeof temstd::cout<<"----"<<std::endl<<len<<std::endl<<"----"<<std::endl;ssize_t m = recvfrom(udpsockfd,buf,sizeof(buf)-1,0,(struct sockaddr*)&tem,&len);std::cout<<"----"<<std::endl<<len<<std::endl<<"----"<<std::endl;if(m < 0){perror("recvfrom fail!");assert(false);}else{buf[m] = 0;std::cout<<"GetFromServer: "<<buf<<std::endl;std::string toserver = "I Get your message\n";if(sendto(udpsockfd,toserver.c_str(),toserver.size(),0,(struct sockaddr*)&tem,len) < 0){perror("sendto fail!");assert(false);}}}sleep(1);}return 0;
}
问题所在
实际在填入len这个参数的时候,需要首先把len初始化为sizeof(tem)(无论是客户端还是服务端),看似len是传地址,是一个输出型参数,但是实际上,它不仅仅起到输出型参数的作用。如果把len按照输出型参数来看待,那么不发送数据还好说,一旦在后文使用了这个len通过sendto来发送数据,就会报错:
四、结论:
在使用recvfrom之前,冷不能仅仅当作一个输出型参数来看待!也需要把len初始化为传进去的(sockaddr_in)结构体的大小!
完~
相关文章:
[错误经验 坑]关于UDP服务器和客户端通信使用的recvfrom的输出型参数len没有被初始化导致的问题
[错误经验 坑]关于UDP服务器和客户端通信使用的recvfrom的输出型参数len没有被初始化导致的问题 水墨不写bug 文章目录 一、困惑:二、解答:(1)函数原型1. int sockfd2. void *buf3. size_t len4. int flags5. struct sockaddr *sr…...
KaiwuDB:面向AIoT场景的多模融合数据库,赋能企业数字化转型
引言 在万物互联的AIoT时代,企业面临着海量时序数据处理、多模数据融合和实时分析等挑战。KaiwuDB应运而生,作为一款面向AIoT场景的分布式、多模融合、支持原生AI的数据库产品,为企业提供了一站式数据管理解决方案。 产品概述 KaiwuDB是一…...
Web3 的云基础设施正在成型,Polkadot 2.0 用三项技术改写“上链成本”
在Web3基础设施内卷加剧的今天,“如何以更低成本、更大灵活性部署一条高性能应用链”正成为开发者们最关心的问题。而刚刚走出“技术慢热”误区的Polkadot,正在用一套名为 Polkadot 2.0 的架构升级方案,重新定义这一问题的解法。 这套升级最…...
Elasticsearch 学习规划
Elasticsearch 学习规划 明确学习目标与动机 场景化需求分析 - **S**:掌握Elasticsearch架构体系,熟练使用Elasticsearch 进行数据分析,Elasticsearch结合java 项目落地案例 - **M**:搜索和Elasticsearch相关GitHub项目 - **A**:每…...
OpenHarmony如何编译安装系统应用(以settings设置为例)
开发环境 1.OpenHarmony 2.DevEco Studio 3 .Full Sdk 实现步骤 1.获取设置应用源码 https://gitee.com/openharmony/applications_settings/tree/OpenHarmony-v5.0.0-Release/ 2,使用 DevEco Studio 和 Full SDK对系统应用进行签名,默认工程是未配置签名的状态,所构建…...
手撕 STL 之—— list
目录 引言 1, list_node类及其构造函数 2, list类的创建 3, list基本功能函数 3_1, 构造函数 3_2,push_back 3_3,push_front 3_4, pop_back 3_5,pop_front 4,迭代器 (重点) 4_1,如何设…...
Med-R1论文阅读理解
论文介绍 这篇论文介绍了一个名为 Med-R1 的新方法,用于提升多模态视觉语言模型(VLM)在医学图像理解和推理任务中的泛化能力和可解释性。下面是对整篇论文的简洁总结: ⸻ 🧠 核心思想 • 当前医学 VLM 多依赖于监督…...
微服务相关
1.SpringCloud有哪些常用组件?分别是什么作用? 注册中心:nacos 负载均衡:rabbion/LoadBalancer 网关:gateway 服务熔断:sential 服务调用:Feign 2.服务注册发现的基本流程是怎样的&#x…...
Linux vagrant 导入Centos到virtualbox
前言 vagrant 导入centos 虚拟机 前提要求 安装 virtualbox 和vagrant<vagrant-disksize> (Linux 方式 Windows 方式) 创建一键部署centos 虚拟机 /opt/vagrant 安装目录/opt/VirtualBox 安装目录/opt/centos8/Vagrantfile (可配置网络IP,内存…...
Spring Boot MongoDB 分页工具类封装 (新手指南)
Spring Boot MongoDB 分页工具类封装 (新手指南) 目录 引言:为何需要分页工具类?工具类一:PaginationUtils - 简化 Pageable 创建 设计目标代码实现 (PaginationUtils.java)如何使用 PaginationUtils 工具类二:PageResponse<…...
第七章 指针
2024-04 2023-10 A 2023-04 2022-10 2022-04 2021-10 2021-04 2020-10 2020-04...
20年AB1解码java
P8706 [蓝桥杯 2020 省 AB1] 解码 - 洛谷 详细代码如下: import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner innew Scanner(System.in); // 接收输入的字符串char [] c in.next().toCharArray(); // 接收 还原的字符…...
《Java实战:密码加密算法实现与代码解析》
文章目录 一、需求背景二、代码逐模块解析1. 主程序入口2. 密码输入模块3. 加密处理模块4. 结果拼接模块 三、完整代码示例四、运行示例五、优化方向(下篇预告) 一、需求背景 实现一个4位数字密码的简单加密系统,规则如下: 输入…...
AllData数据中台升级发布 | 支持K8S数据平台2.0版本
🔥🔥 AllData大数据产品是可定义数据中台,以数据平台为底座,以数据中台为桥梁,以机器学习平台为中层框架,以大模型应用为上游产品,提供全链路数字化解决方案。 ✨杭州奥零数据科技官网…...
Jupyter notebook使用技巧
一、打开指定文件夹 在快捷方式目标中,使用如下代码 anaconda3\python.exe anaconda3\cwp.py anaconda3 anaconda3\python.exe anaconda3\Scripts\jupyter-notebook-script.py --notebook-dirD:\code\python...
6.3es新特性web worker
Web Worker 是 HTML5 提供的多线程技术,允许在浏览器后台创建独立线程执行 JavaScript 代码,解决主线程因耗时任务导致的 界面卡顿 问题。 核心特性 线程隔离:Worker 线程无法直接操作 DOM 或访问 window 对象通信机制:通过 pos…...
基于 OpenHarmony 5.0 的星闪轻量型设备应用开发——Ch3 设备驱动开发
写在前面:本篇是系列文章《基于 OpenHarmony 5.0 的星闪轻量型设备应用开发》的第 3 章。本篇从 GPIO、PWM、I2C、UART 以及 ADC 等方面对基于 OpenHarmony 5.0 的 WS63 设备驱动开发进行了详细的介绍。本篇的篇幅较长,建议先收藏再阅读。 3.1 OpenHarmo…...
iphone各个机型尺寸
以下是苹果(Apple)历代 iPhone 机型 的屏幕尺寸、分辨率及其他关键参数汇总(截至 2023年10月,数据基于官方发布信息): 一、标准屏 iPhone(非Pro系列) 机型屏幕尺寸(英寸…...
OfficePlus去掉PDF文件右键菜单里的PDF转换
今天在吾爱破解论坛看到一个求助帖,说是OfficePlus,安装后,PDF文件的右键菜单里多了PDF转换,想去掉,不知道怎么弄。底下的回复基本都是百度复制或者AI搜索出的答案,大致就是找注册表里CLASSID下的菜单栏相关…...
Linux驱动开发进阶(七)- DRM驱动程序设计
文章目录 1、前言2、DRAM(KMS、GEM)2.1、KMS2.2、GEM 3、DRM3.1、驱动结构体3.2、设备结构体3.3、DRM驱动注册3.4、DRM模式设置3.4.1、plane初始化3.4.2、crtc初始化3.4.3、encoder初始化3.4.4、connect初始化 4、示例说明5、DRM Simple Display框架6、DRM热插拔7、DRM中的plan…...
Parasoft C++Test软件单元测试_条件宏和断言宏使用方法的详细介绍
系列文章目录 Parasoft C++Test软件静态分析:操作指南(编码规范、质量度量)、常见问题及处理 Parasoft C++Test软件单元测试:操作指南、实例讲解、常见问题及处理 Parasoft C++Test软件集成测试:操作指南、实例讲解、常见问题及处理 进阶扩展:自动生成静态分析文档、自动…...
vue辅助工具(vue系列二)
目录 第一章、安装周边库1.1)状态管理:Pinia1.2)路由管理:Router1.3)HTTP 客户端:Axios1.4)UI 组件库:Element 第二章、下载Vue插件并安装2.1)安装开发者工具2.1.1&#…...
WPF 五子棋项目文档
WPF 五子棋项目文档 1. 项目概述 本项目是一个使用 Windows Presentation Foundation (WPF) 技术栈和 C# 语言实现的桌面版五子棋(Gomoku)游戏。它遵循 MVVM(Model-View-ViewModel)设计模式,旨在提供一个结构清晰、可…...
UniApp 实现兼容 H5 和小程序的拖拽排序组件
如何使用 UniApp 实现一个兼容 H5 和小程序的 九宫格拖拽排序组件,实现思路和关键步骤。 一、实现目标 支持拖动菜单项改变顺序拖拽过程实时预览移动位置拖拽松开后自动吸附回网格兼容 H5 和小程序平台 二、功能结构拆解以及完整代码 完整代码: <…...
谷歌推出统一安全平台-一个平台实现跨云网端主动防护
👋 今天要给大家带来一个超级棒的消息!谷歌云推出了全新的“谷歌统一安全平台”,感觉我们的网络安全问题有救啦!😄 随着企业基础设施变得越来越复杂,保护它们也变得越来越难。攻击面不断扩大,安…...
众趣科技丨沉浸式 VR 体验,助力酒店民宿数字化营销宣传
随着旅游季的到来,各地的旅游景区开始“摩拳擦掌”推出各种活动,吸引更多游客来此游玩。 自去年以来,冰雪游热度持续上升,尤其是对于满心期待的南方游客来说,哈尔滨仍是冰雪旅游的热门目的地。据美团数据显示ÿ…...
DAY05:【pytorch】图像预处理
1、torchvision 功能:计算视觉工具包 torchvision.transforms:常用的图像预处理方法torchvision.datasets:常用数据集的 dataset 实战,MINIST,CIFAR-10,ImageNet等torchvision.model:常用的模…...
真实企业级K8S故障案例:ETCD集群断电恢复与数据保障实践
背景描述 某跨境电商平台生产环境使用Kubernetes(v1.23.17)管理500微服务。某日机房突发市电中断,UPS未能及时接管导致: 3节点ETCD集群(v3.5.4)全部异常掉电 Control-Plane节点无法启动api-server 业务P…...
rbd块设备的id修改
背景 看到有这个需求,具体碰到什么场景了不太清楚,之前做过rbd的重构的研究,既然能重构,那么修改应该是比重构还要简单一点的,我们具体看下怎么操作 数据结构分析 rbd的元数据信息 [rootlab104 ~]# rbd create tes…...
WP最主题专业的wordpress主题开发
WP最主题(wpzui.com) WP最主题是一个提供高品质WordPress主题的平台。它注重主题的设计和功能,旨在为用户提供美观且实用的主题选择。其主题通常具有良好的用户体验、丰富的自定义选项以及优化的性能,能够满足不同类型的网站搭建…...
HomeAssistant本地化部署结合内网穿透打造跨网络智能家居中枢
文章目录 前言1. 添加镜像源2. 部署HomeAssistant3. HA系统初始化配置4. HA系统添加智能设备4.1 添加已发现的设备4.2 添加HACS插件安装设备 5. 安装cpolar内网穿透5.1 配置HA公网地址 6. 配置固定公网地址 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂…...
# 实时人脸性别与年龄识别:基于OpenCV与深度学习模型的实现
实时人脸性别与年龄识别:基于OpenCV与深度学习模型的实现 在当今数字化时代,计算机视觉技术正以前所未有的速度改变着我们的生活与工作方式。其中,人脸检测与分析作为计算机视觉领域的重要分支,已广泛应用于安防监控、智能交互、…...
SAP-ABAP:SAP的Open SQL和Native SQL详细对比
在SAP ABAP开发中,Open SQL和Native SQL是两种操作数据库的方式,它们的核心区别在于可移植性、功能范围及底层实现机制。以下是详细对比: 1. Open SQL:深入解析 1.1 核心特性 数据库抽象层 Open SQL 由 SAP 内核的 Database Interface (DBI) 转换为目标数据库的 SQL(如 …...
基于大模型构建金融客服的技术调研
OpenAI-SB api接口 https://openai-sb.com/ ChatGPT与Knowledge Graph (知识图谱)分享交流 https://www.bilibili.com/video/BV1bo4y1w72m/?spm_id_from333.337.search-card.all.click&vd_source569ef4f891360f2119ace98abae09f3f 《要研究的方向和准备》 https://ww…...
Python设计模式:命令模式
1. 什么是命令模式? 命令模式是一种行为设计模式,它将请求封装为一个对象,从而使您能够使用不同的请求、队列或日志请求,以及支持可撤销操作。 命令模式的核心思想是将请求的发送者与请求的接收者解耦,使得两者之间的…...
30天学Java第八天——设计模式
装饰器模式 Decorator Pattern 装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许通过动态地添加功能来扩展对象的行为,而不需要修改原有的类。 这种模式通常用于增强对象的功能,与继承相比,使用…...
Spring事务系列 三
Spring事务的传播机制 Spring事务系列 一-CSDN博客 Spring事务系列 二-CSDN博客 文章目录 系列文章目录 目录 文章目录 前言 一、Spring事务的传播机制 Propagation.REQUIRED: Propagation.SUPPORTS: Propagation.MANDATORY: Propagation.REQUIRES_NEW: Propagation.NOT_SUPPO…...
文件上传做题记录
1,[SWPUCTF 2021 新生赛]easyupload2.0 直接上传php 再试一下phtml 用蚁剑连发现连不上 那就只要命令执行了 2,[SWPUCTF 2021 新生赛]easyupload1.0 当然,直接上传一个php是不行的 phtml也不行,看下是不是前端验证,…...
机器学习的监督学习与无监督学习
机器学习主要分为监督学习和无监督学习两大类,两者的核心区别在于数据是否带有标签(Label)。以下是它们的详细对比和说明: 1. 监督学习(Supervised Learning) 定义:通过带有标签的训练数据&…...
C++ 入门三:函数与模板
一、内联函数:编译期嵌入的 “高效函数” 1. 什么是内联函数? 核心特性:在编译阶段,内联函数的函数体会直接嵌入到调用它的代码中,避免了普通函数的调用开销(如压栈、跳转、返回)。语法&#…...
解析券商qmt的优缺点
现在已经对于大QMT进行了一步步的深入了解与学习,也已经开始积木式搭建策略,进行交易了,但是,随时不断的深入,发现的问题也越来越多。下面开始逐一解析: 首页 | 迅投知识库 这是详细的说明。 目前券商给大…...
CSE lesson2 chrony服务器
CSE lesson2 chrony服务器 timedatectl命令 NTP(network time protocal)网络时间协议,时钟服务器同步时间的时候会使用到该协议进行时间同步。 #关闭/开启时间同步服务 [rootlocalhost ~]# timedatectl set-ntp 0/1#设置时间(必须关闭时间同步服务才能…...
时光交响曲:杭州的科技与传统交响
故事背景 故事发生在中国浙江杭州,以现代科技与文化传统的交融为背景,展现了人与自然、历史的深刻联系。在晨曦中的茶园、宁静的运河书屋、科技堤坝等地方,每个场景都充满了生机与活力,展示了科技如何赋予传统文化新的生命&#x…...
【大模型智能体】Agent2Agent协议加上MCP协议也许会成为未来Agent智能体系统的标配
之前在文章《基于Claude MCP协议的智能体落地示例》、《MCP(Model Context Protocol) 大模型智能体第一个开源标准协议》我们已经对MCP协议做了介绍,MCP提供了将大模型连接到不同数据源和工具的标准方式,包括内容仓库、商业工具和开发环境。 以上解决的是…...
opencv(C++)处理图像颜色
文章目录 介绍使用策略设计模式比较颜色实现方案计算两个颜色向量之间的距离1. 简单方法:曼哈顿距离计算(Manhattan Distance)2.使用 OpenCV 的 cv::norm 函数3.使用 OpenCV 的 cv::absdiff 函数错误示例 使用 OpenCV 函数实现颜色检测实现方…...
2025年焊接与热切割作业证考试真题分享
焊接与热切割作业属于特种作业操作证考试,理论知识点专业性强、安全规范要求高,如何高效备考成为关键!【100分题库】焊接与热切割作业理论备考题库紧扣最新考试大纲,帮你系统掌握考点,一次通过考试! 1、下…...
AI 代码生成工具如何突破 Java 单元测试效能天花板?
一、传统单元测试的四大痛点 时间黑洞:根据 JetBrains 调研,Java 开发者平均花费 35% 时间编写测试代码覆盖盲区:手工测试覆盖率普遍低于 60%(Jacoco 全球统计数据)维护困境:业务代码变更导致 38% 的测试用…...
【C++游戏引擎开发】第13篇:光照模型与Phong基础实现
一、Phong模型数学原理 1.1 光照叠加公式 L = k a I a + k d I d max ( 0 , n ⋅ l ) + k s I s max ( 0 , r ⋅ v ) α L = k_a I_a + k_d I_d \max(0, \mathbf{n} \cdot \mathbf{l}) + k_s I_s \max(0, \mathbf{r} \cdot \mathbf{v})^\alpha L=kaIa+kdIdmax(0…...
如何在Android系统上单编ko?
文章目录 一、先了解编译驱动需要什么?二、配置makefile1、在Android系统编译LOG上找到编译器信息(一般都会打印出来)2、基于源MK构造 可独立运行的makefile3)进入docker,在此makefile目录下敲make4)最后根…...
虚拟dom工作原理以及渲染过程
浏览器渲染引擎工作流程都差不多,大致分为5步,创建DOM树——创建StyleRules——创建Render树——布局Layout——绘制Painting 第一步,用HTML分析器,分析HTML元素,构建一颗DOM树(标记化和树构建)。 第二步,用…...