NDK OpenGL渲染画面效果

news2024/11/13 18:43:04

NDK系列之OpenGL渲染画面效果技术实战,本节主要是通过OpenGL Java库(谷歌对OpenGL C++库做了JIN封装,核心实现还是在Native层),实现页面渲染,自定义渲染特效。

实现效果:

实现逻辑:

1.创建Camera,绑定SurfaceTexture纹理画布对象;

2.将Camera预览画面数据传递给SurfaceTexture,缓存到buffer;

3.OpenGLES获取SurfaceTexture缓存的画面数据,渲染到GLSurfaceView(屏幕)。

本节主要内容:

1.OpenGL理论知识;

2.自定义GLSurfaceView;

3.自定义渲染器Renderer;

4.ScreenFilter封装OpenGL;

5.着色器代码工作。

源码:

NdkOpenGLPlay: NDK OpenGL渲染画面效果

一、OpenGL理论知识

1)图形领域的工业标准,是一套跨编程语言、跨平台的、专业的图形编程(软件)接口。它用于二维、三维图 像,是一个功能强大,调用方便的底层图形库。 可以简单理解为是GPU显卡语言。针对手机、PDA和游戏主机等嵌入式设备而设计的OpenGL API 子集, GLSurfaceView(不仅仅有,SurfaceView的所有功能,还拥有了 OpenGL的处理)。

2)OpenGL绘制流程:

为什么是三角形:三角形是 图像领域最小单元

1.位置排版,顶点位置确定好【顶点位置】

2.根据各个的位置排版,细节的网格排版【光栅化】

3.根据各个的位置排版,细节的网格排版执行逻辑处理【光栅操作逻辑】

4.颜色色彩的准备工作【纹理过滤】

5.片元处理,其实就是上色,绘制成效画面【纹理填充】

6.输出结果 ---> GPU 人类就看到了画面

3)Shader着色器(重点)

着色器(Shader)是运行在GPU上的小程序。

顶点着色器(vertex shader)如何处理顶点、法线等数据的小程序。

片元着色器(fragment shader)如何处理光、阴影、遮挡、环境等等对物体表面的影响,最终生成一 副图像的小程序。

二、自定义GLSurfaceView

GLSurfaceView继承至SurfaceView,不仅仅有SurfaceView的所有功能,还拥有了OpenGL的处理;而MyGLSurfaceView继承至GLSurfaceView,拥有GLSurfaceView的所有能力,支持自定义渲染器(render),可以灵活的进行OpenGL渲染。

public class MyGLSurfaceView extends GLSurfaceView {

    public MyGLSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        // TODO 一:设置EGL版本
        // 2 代表是 OpenGLES 2.0
        setEGLContextClientVersion(2);

        // TODO 二:设置渲染器
        // 注意:
        // EGL 开启一个 GLThread.start  run { Renderer.onSurfaceCreated ...onSurfaceChanged  onDrawFrame }
        // 如果这三个函数,不让GLThread调用,会崩溃,所以他内部的设计,必须通过GLThread调用来调用三个函数
        setRenderer(new MyGlRenderer(this)); // this 自定义渲染器 会回调回来做处理,所有传递this

        // TODO 三:设置渲染器模式
        // RENDERMODE_WHEN_DIRTY 按需渲染,有帧数据的时候,才会去渲染( 效率高,麻烦,后面需要手动调用一次才行)
        // RENDERMODE_CONTINUOUSLY 每隔16毫秒,读取更新一次,(如果没有显示上一帧)
        setRenderMode(RENDERMODE_WHEN_DIRTY); // 手动模式 - 效率高,麻烦,后面需要手动调用一次才行
    }
}

三、自定义渲染器Renderer

1.实现GLSurfaceView.Renderer接口,实现接口的onSurfaceCreated()、onSurfaceChanged()和onDrawFrame()方法;

1)当Surface创建时,回调onSurfaceCreated()函数,创建CameraHelper对象;创建SurfaceTexture纹理对象,并绑定SurfaceTexture.OnFrameAvailableListener监听;创建ScreenFilter屏幕过滤器。

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
	Log.i(TAG, "onSurfaceCreated");
	mCameraHelper = new CameraHelper((Activity) myGLSurfaceView.getContext(), // 上下文
			Camera.CameraInfo.CAMERA_FACING_FRONT, // 前置摄像头
			640, 480);
	// 获取纹理ID【先理解成画布】
	mTextureID = new int[1];
	/**
	 * 1.长度 只有一个 1
	 * 2.纹理ID,是一个数组
	 * 3.offset:0 使用数组的0下标
	 */
	glGenTextures(mTextureID.length, mTextureID, 0);
	mSurfaceTexture = new SurfaceTexture(mTextureID[0]); // 实例化纹理对象
	mSurfaceTexture.setOnFrameAvailableListener(this); // 绑定好此监听 SurfaceTexture.OnFrameAvailableListener
	mScreenFilter = new ScreenFilter(myGLSurfaceView.getContext());
}

2)当Surface改变时,回调onSurfaceChanged()函数,获得Camera对象,设置Camera绑定SurfaceTexture纹理对象,开启相机预览。

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
	Log.i(TAG, "onSurfaceChanged");
	mCameraHelper.startPreview(mSurfaceTexture); // 开始预览
	mScreenFilter.onReady(width, height);
}

实例化CameraHelper,打开Camera,设置Camera绑定SurfaceTexture纹理对象,开启相机预览。

public void startPreview(SurfaceTexture surfaceTexture) {
	mSurfaceTexture = surfaceTexture; // TODO 重点
	try {
		// 获得camera对象
		mCamera = Camera.open(mCameraID);
		// 配置camera的属性
		Camera.Parameters parameters = mCamera.getParameters();
		// 设置预览数据格式为nv21
		parameters.setPreviewFormat(ImageFormat.NV21);
		// 这是摄像头宽、高
		setPreviewSize(parameters);
		// 设置摄像头 图像传感器的角度、方向
		setPreviewOrientation(parameters);
		mCamera.setParameters(parameters);
		cameraBuffer = new byte[mWidth * mHeight * 3 / 2];  // 请看之前讲过的的细节
		cameraBuffer_ = new byte[mWidth * mHeight * 3 / 2]; // 请看之前讲过的的细节
		// 数据缓存区
		mCamera.addCallbackBuffer(cameraBuffer);
		mCamera.setPreviewCallbackWithBuffer(this);
		// 设置预览画面(之前的方式:把显示的画面,渲染到SurfaceView屏幕上即可)
		// mCamera.setPreviewDisplay(mSurfaceHolder); // SurfaceView 和 Camera绑定 ,以前音视频推流,就是这个干的

		// 设置预览画面(离屏渲染) surfaceTexture纹理画布(仅仅只是缓存一份画布,不可见的画布) 配合 OpenGL渲染操作
		// Camera相机预览数据 ---->  surfaceTexture纹理画布(不可见的画布) ---> OpenGL TODO 重点,绑定纹理
		mCamera.setPreviewTexture(surfaceTexture); // OpenGL无法直接访问到 Camera预览数据, 他只能访问 surfaceTexture
		
		// 开启预览
		mCamera.startPreview();
	} catch (Exception e) {
		e.printStackTrace();
	}
}

3)绘制一帧图像时,回调onDrawFrame()函数,获取纹理对象的图像数据,通过OpenGL渲染到屏幕;

@Override
public void onDrawFrame(GL10 gl) {
	Log.i(TAG, "onDrawFrame");
	// 每次清空之前的:例子:上课擦黑白 是一个道理
	glClearColor(255, 0, 0, 0); // 屏幕清理成颜色 红色,清理成红色的黑板一样
	// mask 细节看看此文章:https://blog.csdn.net/z136411501/article/details/83273874
	// GL_COLOR_BUFFER_BIT 颜色缓冲区
	// GL_DEPTH_BUFFER_BIT 深度缓冲区
	// GL_STENCIL_BUFFER_BIT 模型缓冲区
	glClear(GL_COLOR_BUFFER_BIT);

	// 绘制摄像头数据
	mSurfaceTexture.updateTexImage();  // 将纹理图像更新为图像流中最新的帧数据【刷新一下】
	// 画布,矩阵数据,通过Native层将数据存储到mtx
	mSurfaceTexture.getTransformMatrix(mtx);
	// 绘制一帧图像
	mScreenFilter.onDrawFrame(mTextureID[0], mtx);
}

2.实现SurfaceTexture.OnFrameAvailableListener接口,实现接口的onFrameAvailable()方法;

当有可用的数据时,回调onFrameAvailable()函数,手动调用,触发屏幕渲染

@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
	Log.i(TAG, "onFrameAvailable");
	myGLSurfaceView.requestRender(); // setRenderMode(RENDERMODE_WHEN_DIRTY); 配合用
}

四、ScreenFilter封装OpenGL

1.初始化ScreenFilter操作:

1)读取顶点着色器和片元着色器代码,转换为字符串

String vertexSource = readTextFileFromResource(context, R.raw.camera_vertex); 
String fragmentSource = readTextFileFromResource(context, R.raw.camera_fragment); 

2)配置顶点着色器

// 1.1 创建顶点着色器
int vShaderId = glCreateShader(GL_VERTEX_SHADER);
// 1.2 绑定着色器源代码到 着色器(加载着色器的代码)
glShaderSource(vShaderId, vertexSource);
// 1.3 编译着色器代码(编译阶段:编译成功就能拿到顶点着色器ID,编译失败基本上就是着色器代码字符串写错了)
glCompileShader(vShaderId);
// 1.4 获取着色器配置结果
int[] status = new int[1];
glGetShaderiv(vShaderId, GL_COMPILE_STATUS, status, 0);
if (status[0] != GL_TRUE) {
	throw new IllegalStateException("顶点着色器配置失败!");
}

3)配置片元着色器

// 2.1 创建片元着色器
int fShaderId = glCreateShader(GL_FRAGMENT_SHADER);
// 2.2 绑定着色器源代码到 着色器(加载着色器的代码)
glShaderSource(fShaderId, fragmentSource);
// 2.3 编译着色器代码(编译阶段:编译成功就能拿到顶点着色器ID,编译失败基本上就是着色器代码字符串写错了)
glCompileShader(fShaderId);
// 2.4 获取着色器配置结果
glGetShaderiv(fShaderId, GL_COMPILE_STATUS, status, 0);
if (status[0] != GL_TRUE) {
	throw new IllegalStateException("片元着色器配置失败!");
}

4)配置着色器程序

// 3.1 创建一个着色器程序
mProgram = glCreateProgram();
// 3.2 将前面配置的 顶点 和 片元 着色器 附加到新的程序 上
glAttachShader(mProgram, vShaderId); // 顶点
glAttachShader(mProgram, fShaderId); // 片元
// 3.3 链接着色器
glLinkProgram(mProgram); // mProgram着色器程序 是我们的成果
// 3.4 获取着色器配置结果
glGetShaderiv(mProgram, GL_LINK_STATUS, status, 0);
if (status[0] != GL_TRUE) {
	throw new IllegalStateException("着色器程序链接失败!");
}

5)获取顶点着色器和片元着色器代码的变量的索引值,通过索引来赋值

// 顶点着色器里面的如下:
vPosition = glGetAttribLocation(mProgram, "vPosition"); // 顶点着色器:的索引值
vCoord = glGetAttribLocation(mProgram, "vCoord"); // 顶点着色器:纹理坐标,采样器采样图片的坐标 的索引值
vMatrix = glGetUniformLocation(mProgram, "vMatrix"); // 顶点着色器:变换矩阵 的索引值

// 片元着色器里面的如下:
vTexture = glGetUniformLocation(mProgram, "vTexture"); // 片元着色器:采样器

6)缓存顶点坐标(顶点:位置 排版)

mVertexBuffer = ByteBuffer.allocateDirect(4 * 2 * 4) // 分配内存 坐标个数 * xy坐标数据类型 * float占几字节
		.order(ByteOrder.nativeOrder()) // 使用本地字节序,例如:大端模式,小端模式,这里设置为:跟随OpenGL的变化二变化
		.asFloatBuffer();
mVertexBuffer.clear(); // 清除一下
float[] v = { // OpenGL世界坐标
		-1.0f, -1.0f,
		1.0f, -1.0f,
		-1.0f, 1.0f,
		1.0f, 1.0f,
};
mVertexBuffer.put(v);

7)缓存纹理坐标(纹理:上色 成果)

mTexturBuffer = ByteBuffer.allocateDirect(4 * 2 * 4) // 分配内存 坐标个数 * xy坐标数据类型 * float占几字节
		.order(ByteOrder.nativeOrder()) // 使用本地字节序,例如:大端模式,小端模式,这里设置为:跟随OpenGL的变化二变化
		.asFloatBuffer();
mTexturBuffer.clear(); // 清除一下
// 旋转 180度 就纠正了
float[] t = { // 屏幕坐标系
		1.0f, 0.0f,
		0.0f, 0.0f,
		1.0f, 1.0f,
		0.0f, 1.0f,
};
mTexturBuffer.put(t);

2.绘制操作

通过OpenGL顶点着色器,规划位置;设置顶点坐标相当于,相机的四个点位置排版;设置纹理坐标,用来图形上色;设置图形矩阵数据;

通过OpenGL片元着色器,给图片上色;设置采样器,获取顶点着色器设置的纹理坐标和矩阵数据的最终计算成果,通知OpenGL绘制。

1)顶点着色器

// TODO 1.1 顶点坐标赋值  NIO的Buffer 用它就要归零,习惯
mVertexBuffer.position(0); // 养成好习惯,每次来用他时,归零(为了从坐标位置的起始开始)
/**
 * 传值(把float[]值传递给顶点着色器)把mVertexBuffer传递到vPosition == size:每次两个xy, stride:0 不跳步
 * 1.着色器代码里面的 标记变量 attribute vec4 vPosition;
 * 2.xy 所以是两个
 * 3.不用管
 * 4.不用管
 * 5.跳步 0 不跳步
 * 6.顶点坐标nio的buffer缓存数据
 */
glVertexAttribPointer(vPosition, 2, GL_FLOAT, false, 0, mVertexBuffer);
// 激活
glEnableVertexAttribArray(vPosition);

// TODO 1.2 纹理坐标赋值
mTexturBuffer.position(0); // 养成好习惯,每次来用他时,归零(为了从坐标位置的起始开始)
// 传值(把float[]值传递给纹理)把mTexturBuffer传递到vCoord == size:每次两个xy, stride:不跳步
glVertexAttribPointer(vCoord, 2, GL_FLOAT, false, 0, mTexturBuffer);
// 激活
glEnableVertexAttribArray(vCoord);

// TODO 1.3 变换矩阵 把mtx矩阵数据 传递到 vMatrix
glUniformMatrix4fv(vMatrix, 1, false, mtx, 0);

2)片元着色器

// 激活图层
glActiveTexture(GL_TEXTURE0);
// TODO 2.1 绑定纹理ID --- glBindTexture(GL_TEXTURE_2D ,textureId); 如果在片元着色器中的vTexture,不是samplerExternalOES类型,就可以这样写
glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID); // 由于我们的着色器代码是 使用了 samplerExternalOES
// TODO 2.2 采样器赋值
glUniform1i(vTexture, 0); // 传递参数 给 片元着色器:采样器
// TODO 2.3 通知 opengl 绘制 ,从0开始,共四个点绘制
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

五、着色器代码工作

1)顶点着色器

attribute vec4 vPosition; // 顶点坐标,相当于:相机的四个点位置排版

attribute vec4 vCoord; // 纹理坐标,用来图形上色的

uniform mat4 vMatrix; // 变换矩阵,4*4的格式的

varying vec2 aCoord; // 把这个最终的计算成果,给片元着色器 【不需要Java传递,他是计算出来的】

void main() {
    gl_Position = vPosition; // 确定好位置排版

    aCoord = (vMatrix * vCoord).xy; // 兼容所有设备
}

2)片元着色器

// 导入 samplerExternalOES 的意思
#extension GL_OES_EGL_image_external : require

// float 数据的精度 (precision lowp = 低精度) (precision mediump = 中精度) (precision highp = 高精度)
precision mediump float;

// 根据上面的数据的精度,写下面的 采样器 相机的数据
// uniform sampler2D vTexture;  由于我们用的是 安卓的相机,就不能用他
uniform samplerExternalOES vTexture; // samplerExternalOES才能采样相机的数据

varying vec2 aCoord; // 把这个最终的计算成果,给片元着色器,拿到最终的成果,我才能上色

void main() {
    // texture2D (采样器, 坐标) 正常效果
    // gl_FragColor = texture2D(vTexture, aCoord);

    // 305911公式:黑白电视效果,其实原理就是提取出Y分量
    /*vec4 rgba =texture2D(vTexture, aCoord);
    float gray = (0.30 * rgba.r   + 0.59 * rgba.g + 0.11* rgba.b); // 其实原理就是提取出Y分量 ,就是黑白电视
    gl_FragColor = vec4(gray, gray, gray, 1.0);*/

    // 底片效果
    vec4 rgba = texture2D(vTexture,aCoord);  // rgba
    gl_FragColor = vec4(1.-rgba.r, 1.-rgba.g, 1.-rgba.b, rgba.a);
}

至此,OpenGL渲染画面效果技术实战项目已完成;黑白电视和大眼萌等特效都可以通过OpenGL实现。

源码:

NdkOpenGLPlay: NDK OpenGL渲染画面效果

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

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

相关文章

如何学习FPGA?莱迪斯深力科电子LCMXO2-4000HC-4TG144C MachXO2系列 FPGA可编程逻辑简介

如何学习FPGA?莱迪斯深力科电子LCMXO2-4000HC-4TG144C MachXO2系列 FPGA可编程逻辑简介 FPGA是英文Field-Programmable Gate Array的缩写,即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。它是作…

【高分论文密码】大尺度空间模拟预测与数字制图

大尺度空间模拟预测和数字制图技术和不确定性分析广泛应用于高分SCI论文之中,号称高分论文密码。大尺度模拟技术可以从不同时空尺度阐明农业生态环境领域的内在机理和时空变化规律,又可以为复杂的机理过程模型大尺度模拟提供技术基础。在本次培训中&…

查询优化之单表查询

建表 CREATE TABLE IF NOT EXISTS article ( id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, author_id INT(10) UNSIGNED NOT NULL, category_id INT(10) UNSIGNED NOT NULL, views INT(10) UNSIGNED NOT NULL, comments INT(10) UNSIGNED NOT NULL, title VARBI…

Ajax和Json综合案例

1. 查询所有 创建brand.html,使用axios发送请求&#xff0c;其中查询一般采用get的请求方式 <script src"js/axios-0.18.0.js"></script><script>//1. 当页面加载完成后&#xff0c;发送ajax请求window.onload function () {//2. 发送ajax请求axi…

星辰天合亮相 2023 国际金融展,软件定义存储信创方案备受瞩目

4 月 25 日&#xff0c;为期三天的 2023 中国国际金融展在北京首钢会展中心开幕&#xff0c;本届展会以“荟萃金融科技成果&#xff0c;展现数字金融力量&#xff0c;谱写金融服务中国式现代化新篇章”为主题&#xff0c;全面展示金融业为完善科技创新体系、加快实现高水平科技…

轻量级「行泊一体」爆发前夜!这家智驾Tier1正加码抢占市场

伴随行泊一体成为产业演进的确定性趋势&#xff0c;如何踩准市场爆发的节奏成为重中之重。 高工智能汽车注意到&#xff0c;行泊一体当前呈分层发展趋势&#xff0c;从底层SOC算力划分&#xff1a;其一&#xff0c;5-20TOPS轻量级平台&#xff0c;提供基础L2级行车泊车需求&am…

被修饰成单栋的倾斜摄影处理思路

作者&#xff1a;kele 前言 倾斜摄影数据是三维项目系统中的常客。在某些项目中&#xff0c;为了给倾斜摄影上的建筑赋予属性信息&#xff0c;实现点击建筑高亮并展示属性的功能&#xff0c;客户将倾斜摄影数据进行了模型单体化&#xff08;使用pdmodeler或者其它软件&#xf…

Java 版Spring cloud 企业工程项目管理系统平台源码(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…

思科实验 voip通信的配置(内附命令超详细)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的绽放&#xff0…

leetcode-328 奇偶链表

题目如下&#xff1a; 给定单链表的头节点 head &#xff0c;将所有索引为奇数的节点和索引为偶数的节点分别组合在一起&#xff0c;然后返回重新排序的列表。 第一个节点的索引被认为是 奇数 &#xff0c; 第二个节点的索引为 偶数 &#xff0c;以此类推。 请注意&#xff0c;…

10个必须掌握的SQL常用语句

世界上70%的相关性数据可以被储存为表格数据&#xff0c;即类似Excel&#xff0c;Csv类型的数据&#xff0c;如何去查询和分析相关性的数据&#xff1f;对于少量数据&#xff0c;我们可以使用Excel&#xff0c;更多一点数据&#xff0c;我们可以使用Python, pandas 处理大数据 …

区块链学习一(FISCO BCOS部署控制台部署第一个HelloWorld)

系统环境&#xff1a;CentOS Linux release 7.6.1810 fisco版本&#xff1a;3.3.0 jdk版本&#xff1a;1.8 第一步 安装依赖 sudo yum install -y curl openssl openssl-devel wget第二步 创建操作目录 mkdir fiscocd fisco第三步 下载安装脚本 curl -LO https://github.co…

chatGPT推荐2个key免费使用

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 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同时推荐一下一个国内比较稳定的代理 #查询余额 curl https://api.openai-proxy.com/pro/balance?apiKeysk-XXX | jqPython代码也可以查询 import requests impor…

生成对抗网络CycleGAN

1.介绍 论文&#xff1a;Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks 论文地址&#xff1a;https://arxiv.org/abs/1703.10593 什么是CycleGAN&#xff1a;CycleGAN主要用于图像之间的转换&#xff0c;假设有两个不成对的图像X和Y&am…

c++11 标准模板(STL)(std::priority_queue)(三)

适配一个容器以提供优先级队列 std::priority_queue 定义于头文件 <queue> template< class T, class Container std::vector<T>, class Compare std::less<typename Container::value_type> > class priority_queue; priority_queu…

chatgpt接入ROS2控制小海龟

chatgpt接入ROS2控制小海龟 0.前言一、使用功能测试&#xff1a; 二、运行结果三、总结 0.前言 在小破站看到的案例&#xff0c;感觉很有趣就自己尝试复现了一下。需要一个OpenAI API Key、ubuntu以及安装ROS2环境。 一、使用 代码仓库在这里&#xff0c;示例操作可以参考B站视…

DATAX hdfsreader orc格式读取数据丢失问题

最近做一个数据同步任务&#xff0c;从hive仓库同步数据到pg&#xff0c;Hive有4000w多条数据&#xff0c;但datax只同步了280w就结束了&#xff0c;也没有任何报错。 看了下datax源码&#xff0c;找到HdfsReader模块DFSUtil核心实现源码读取orc格式的文件方法&#xff1a; pu…

应用运行环境实时洞察,亚马逊云科技Cisco AppDynamics展优势

Cisco AppDynamics(APM)产品&#xff0c;现已正式上线亚马逊云科技Marketplace&#xff08;中国区域&#xff09;。可以通过亚马逊云科技Marketplace&#xff08;中国区域&#xff09;网站&#xff0c;灵活便捷地部署该解决方案&#xff0c;以便充分利用云原生APM(应用性能管理…

(上)苹果有开源,但又怎样呢?

苹果&#xff08;Apple Inc.&#xff09;有多伟大&#xff0c;我相信已经无需赘述了。但是&#xff0c;这里的伟大是指用产品和理念对行业进行的革命性颠覆&#xff0c;而不是对开源而言。 相反&#xff0c;在某种程度上&#xff0c;苹果几乎就是开源的反义词。这种骨子里的 “…

8个Wireshark使用技巧

一&#xff1a;数据包过滤 过滤需要的IP地址 ip.addr 在数据包过滤的基础上过滤协议ip.addrxxx.xxx.xxx.xxx and tcp 过滤端口ip.addrxxx.xxx.xxx.xxx and http and tcp.port80 指定源地址 目的地址ip.srcxxx.xxx.xxx.xxx and ip.dstxxx.xxx.xxx.xxx SEQ字段&#xff08;序列号…