Android 大版本升级变更截图方法总结

Android 大版本升级变更截图方法总结

  • 一、Android R (11) 平台
  • 二、Android S (12) 平台
  • 三、Android U (14) 平台

Android 原生的截屏功能是集成在 SystemUI 中,因此我们普通应用想要获取截图方法,就需要研读下 SystemUI 截屏部分的功能实现。

在这里插入图片描述

一、Android R (11) 平台

SystemUI中截屏时获取当前的屏幕截图方法如下

frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshotMoreAction.java

private Bitmap captureScreenshotBitmap() {
    mDisplay.getRealMetrics(mDisplayMetrics);
    float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
    int rot = mDisplay.getRotation();
    Rect sourceCrop = new Rect(0, 0, (int) dims[0], (int) dims[1]);
    // Take the screenshot
    Bitmap bitmap = SurfaceControl.screenshot(sourceCrop, (int) dims[0], (int) dims[1], rot);
    Log.d(TAG, "capture screenshot bitmap");
    if (bitmap == null) {
        Log.d(TAG, "capture screenshot bitmap is null!");
    }
    return bitmap;
}

核心代码:SurfaceControl.screenshot(sourceCrop, (int) dims[0], (int) dims[1], rot)

关于 SurfaceControl.screenshot 的具体实现查看源码如下

frameworks/base/core/java/android/view/SurfaceControl.java

/**
 * @see SurfaceControl#screenshot(Rect, int, int, boolean, int)}
 * @hide
 */
@UnsupportedAppUsage
public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
    return screenshot(sourceCrop, width, height, false, rotation);

/**
 * Copy the current screen contents into a hardware bitmap and return it.
 * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap into
 * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
 *
 * CAVEAT: Versions of screenshot that return a {@link Bitmap} can be extremely slow; avoid use
 * unless absolutely necessary; prefer the versions that use a {@link Surface} such as
 * {@link SurfaceControl#screenshot(IBinder, Surface)} or {@link GraphicBuffer} such as
 * {@link SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}.
 *
 * @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}
 * @hide
 */
@UnsupportedAppUsage
public static Bitmap screenshot(Rect sourceCrop, int width, int height,
        boolean useIdentityTransform, int rotation) {
    // TODO: should take the display as a parameter
    final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
    if (displayToken == null) {
        Log.w(TAG, "Failed to take screenshot because internal display is disconnected");
        return null;
    }

    if (rotation == ROTATION_90 || rotation == ROTATION_270) {
        rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
    }

    SurfaceControl.rotateCropForSF(sourceCrop, rotation);
    final ScreenshotGraphicBuffer buffer = screenshotToBuffer(displayToken, sourceCrop, width,
            height, useIdentityTransform, rotation);

    if (buffer == null) {
        Log.w(TAG, "Failed to take screenshot");
        return null;
    }
    return Bitmap.wrapHardwareBuffer(buffer.getGraphicBuffer(), buffer.getColorSpace());
}

看到注解@UnsupportedAppUsage,这个注解的存在旨在提醒开发者,某些 API 或代码元素可能在未来版本中发生变化,可能会有风险或不稳定。

@UnsupportedAppUsage 注解,用于标记不建议应用程序使用的 API。它通常用于标记已被弃用或将在未来版本中删除的 API。

作为普通应用,我们需要兼容多版本,所以在使用高targetSdkVersion时,此方法在SDK中就会找不到,因此我们需要使用反射来完成。在 Android R (11) 上可使用的截图工具方法如下:

private static Bitmap screenshotR(int width, int height, Display defaultDisplay) {
    Bitmap bmp = null;
    Rect sourceCrop = new Rect(0, 0, width, height);
    try {
        Class<?> demo = Class.forName("android.view.SurfaceControl");
        Method method = demo.getMethod("screenshot", Rect.class, int.class, int.class, int.class);
        bmp = (Bitmap) method.invoke(null, sourceCrop, (int) width, (int) height,
                defaultDisplay.getRotation());
    } catch (Exception e) {
        e.printStackTrace();
    }
    return bmp;
}

二、Android S (12) 平台

Android S (12)Android T (13) 平台截图方法无变化,SystemUI 中相比较于 R 平台,代码有变化,梳理下代码找到截屏时获取当前的屏幕截图方法如下

frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java

private Bitmap captureScreenshot(Rect crop) {
    int width = crop.width();
    int height = crop.height();
    Bitmap screenshot = null;
    final Display display = getDefaultDisplay();
    final DisplayAddress address = display.getAddress();
    if (!(address instanceof DisplayAddress.Physical)) {
        Log.e(TAG, "Skipping Screenshot - Default display does not have a physical address: "
                + display);
    } else {
        final DisplayAddress.Physical physicalAddress = (DisplayAddress.Physical) address;
        final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(
                physicalAddress.getPhysicalDisplayId());
        final SurfaceControl.DisplayCaptureArgs captureArgs =
                new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
                        .setSourceCrop(crop)
                        .setSize(width, height)
                        .build();
        final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
                SurfaceControl.captureDisplay(captureArgs);
        screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
    }
    return screenshot;
}

核心代码:SurfaceControl.captureDisplay(captureArgs)

关于 SurfaceControl.captureDisplay 的具体实现需要查看源码,这里多了几个新类DisplayCaptureArgsScreenshotHardwareBuffer

frameworks/base/core/java/android/view/SurfaceControl.java

/**
 * @param captureArgs Arguments about how to take the screenshot
 * @param captureListener A listener to receive the screenshot callback
 * @hide
 */
public static int captureDisplay(@NonNull DisplayCaptureArgs captureArgs,
        @NonNull ScreenCaptureListener captureListener) {
    return nativeCaptureDisplay(captureArgs, captureListener);
}

/**
 * Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with
 * the content.
 *
 * @hide
 */
public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) {
    SyncScreenCaptureListener screenCaptureListener = new SyncScreenCaptureListener();

    int status = captureDisplay(captureArgs, screenCaptureListener);
    if (status != 0) {
        return null;
    }

    return screenCaptureListener.waitForScreenshot();
}

在 Android S 和 Android T 上可使用的截图工具方法如下:

private static Bitmap screenshotS(int width, int height, Display defaultDisplay) {
    Bitmap bmp;
    Rect sourceCrop = new Rect(0, 0, width, height);
    final DisplayAddress.Physical physicalAddress = (DisplayAddress.Physical) defaultDisplay.getAddress();
    final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(
            physicalAddress.getPhysicalDisplayId());
    final SurfaceControl.DisplayCaptureArgs captureArgs =
            new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
                    .setSourceCrop(sourceCrop)
                    .setSize(width, height)
                    .build();
    final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
            SurfaceControl.captureDisplay(captureArgs);
    bmp = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
    return bmp;
}

上诉工具类中DisplayAddress.Physical和SurfaceControl.DisplayCaptureArgs为hide类,SurfaceControl.getPhysicalDisplayTokenSurfaceControl.captureDisplayhide方法,所以需要使用反射方法来实现,下述代码为反射的实现:

public static Bitmap screenshotS(int width, int height, Display defaultDisplay) {
    Bitmap bmp = null;
    Rect sourceCrop = new Rect(0, 0, width, height);
    try {
        Class<?> displayAddressClass = Class.forName("android.view.DisplayAddress$Physical");
        Object physicalAddress =  displayAddressClass.getMethod("getPhysicalDisplayId").invoke(defaultDisplay.getAddress());

        Class<?> surfaceControlClass = Class.forName("android.view.SurfaceControl");
        Method getPhysicalDisplayTokenMethod = surfaceControlClass.getMethod("getPhysicalDisplayToken", long.class);
        Object displayToken = getPhysicalDisplayTokenMethod.invoke(null,physicalAddress);

        Class<?> displayCaptureArgsBuilderClass = Class.forName("android.view.SurfaceControl$DisplayCaptureArgs$Builder");
        Constructor<?> displayCaptureArgsBuilderConstructor = displayCaptureArgsBuilderClass.getDeclaredConstructor(IBinder.class);
        Object displayCaptureArgsBuilder = displayCaptureArgsBuilderConstructor.newInstance(displayToken);
        Method setSourceCropMethod = displayCaptureArgsBuilderClass.getMethod("setSourceCrop", Rect.class);
        Method setSizeMethod = displayCaptureArgsBuilderClass.getMethod("setSize", int.class, int.class);
        Method buildMethod = displayCaptureArgsBuilderClass.getMethod("build");
        setSourceCropMethod.invoke(displayCaptureArgsBuilder, sourceCrop);
        setSizeMethod.invoke(displayCaptureArgsBuilder, width, height);
        Object captureArgs = buildMethod.invoke(displayCaptureArgsBuilder);

        Method captureDisplayMethod = surfaceControlClass.getMethod("captureDisplay", captureArgs.getClass());
        Object screenshotBuffer = captureDisplayMethod.invoke(null, captureArgs);

        if (screenshotBuffer != null) {
            Class<?> screenshotHardwareBufferClass = Class.forName("android.view.SurfaceControl$ScreenshotHardwareBuffer");
            Method asBitmapMethod = screenshotHardwareBufferClass.getMethod("asBitmap");
            bmp = (Bitmap) asBitmapMethod.invoke(screenshotBuffer);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return bmp;
}

三、Android U (14) 平台

Android 14 平台上的 SystemUI 中的截图方法类是使用Kotlin编写

frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt

override fun captureDisplay(displayId: Int, crop: Rect?): Bitmap? {
    val captureArgs = CaptureArgs.Builder()
        .setSourceCrop(crop)
        .build()
    val syncScreenCapture = ScreenCapture.createSyncCaptureListener()
    windowManager.captureDisplay(displayId, captureArgs, syncScreenCapture)
    val buffer = syncScreenCapture.getBuffer()
    return buffer?.asBitmap()
}

我这里将 Kotlin 转化为 Java 编写的代码

// 导包为隐藏方法,请使用反射重写此代码
import android.view.IWindowManager;
import android.window.ScreenCapture;
import android.window.ScreenCapture.CaptureArgs;
import android.window.ScreenCapture.SynchronousScreenCaptureListener;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;

IWindowManager windowManager = IWindowManager.Stub.asInterface(ServiceManager.getServiceOrThrow(Context.WINDOW_SERVICE));
CaptureArgs captureArgs = new CaptureArgs.Builder()
        .setSourceCrop(sourceCrop)
        .build();
SynchronousScreenCaptureListener syncScreenCapture = ScreenCapture.createSyncCaptureListener();
windowManager.captureDisplay(defaultDisplay.getDisplayId(), captureArgs, syncScreenCapture);
ScreenshotHardwareBuffer buffer = syncScreenCapture.getBuffer();
if (buffer != null) {
    bitmap = buffer.asBitmap();
}

核心代码:windowManager.captureDisplay(displayId, captureArgs, syncScreenCapture)

之前的方法都封装在了SurfaceControl中,最新的U平台将逻辑挪到了IWindowManager

frameworks/base/core/java/android/view/IWindowManager.aidl

/**
  * Captures the entire display specified by the displayId using the args provided. If the args
  * are null or if the sourceCrop is invalid or null, the entire display bounds will be captured.
  */
 oneway void captureDisplay(int displayId, in @nullable ScreenCapture.CaptureArgs captureArgs,
         in ScreenCapture.ScreenCaptureListener listener);

// aidl 是接口,相关实现在 WindowManagerService 中
//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
@Override
public void captureDisplay(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs,
        ScreenCapture.ScreenCaptureListener listener) {
    Slog.d(TAG, "captureDisplay");
    if (!checkCallingPermission(READ_FRAME_BUFFER, "captureDisplay()")) {
        throw new SecurityException("Requires READ_FRAME_BUFFER permission");
    }

    ScreenCapture.LayerCaptureArgs layerCaptureArgs = getCaptureArgs(displayId, captureArgs);
    ScreenCapture.captureLayers(layerCaptureArgs, listener);

    if (Binder.getCallingUid() != SYSTEM_UID) {
        // Release the SurfaceControl objects only if the caller is not in system server as no
        // parcelling occurs in this case.
        layerCaptureArgs.release();
    }
}

IWindowManagerWindowManager 是 Android 系统中的两个不同的类,它们有以下区别:

  1. 接口 vs 类:IWindowManager 是一个接口,定义了窗口管理器的方法和功能,而 WindowManager 是一个具体的实现类,用于实际管理窗口的显示和操作。

  2. 系统服务 vs 上下文获取:IWindowManager 通常是通过系统服务机制获取的,可以通过 ServiceManager.getService("window") 来获取 IWindowManager 的实例。而 WindowManager 是通过上下文(Context)的 getSystemService() 方法获取的,例如 context.getSystemService(Context.WINDOW_SERVICE)

  3. 系统级权限 vs 应用级权限:IWindowManager 通常被用于系统级别的窗口管理,例如修改窗口属性、调整窗口的位置和大小等,因此访问 IWindowManager 需要特定的系统级权限。相比之下,应用程序可以通过 WindowManager 类来管理自己的窗口,但受到应用程序权限的限制。

总的来说,IWindowManager 是用于系统级窗口管理的接口,而 WindowManager 是用于应用程序级窗口管理的类。在大多数情况下,应用程序开发者更常使用 WindowManager 类来管理应用程序的窗口。

在 Android U (14) 上可使用的截图工具方法如下:

private static Bitmap screenshotU(int width, int height, Display defaultDisplay) {
    Bitmap bmp = null;
    Rect sourceCrop = new Rect(0, 0, width, height);
    try {
        IWindowManager windowManager = IWindowManager.Stub.asInterface(ServiceManager.getServiceOrThrow(Context.WINDOW_SERVICE));
        Class<?> screenCaptureClass = Class.forName("android.window.ScreenCapture");
        Class<?> captureArgsClass = Class.forName("android.window.ScreenCapture$CaptureArgs");
        Class<?> captureArgsBuilderClass = Class.forName("android.window.ScreenCapture$CaptureArgs$Builder");
        Class<?> screenCaptureListenerClass = Class.forName("android.window.ScreenCapture$ScreenCaptureListener");
        Class<?> synchronousScreenCaptureListenerClass = Class.forName("android.window.ScreenCapture$SynchronousScreenCaptureListener");
        Class<?> screenshotHardwareBufferClass = Class.forName("android.window.ScreenCapture$ScreenshotHardwareBuffer");
        Method setSourceCropMethod = captureArgsBuilderClass.getDeclaredMethod("setSourceCrop", Rect.class);
        Object captureArgsBuilder = captureArgsBuilderClass.newInstance();
        setSourceCropMethod.invoke(captureArgsBuilder, sourceCrop);
        Method buildMethod = captureArgsBuilderClass.getDeclaredMethod("build");
        Object captureArgs = buildMethod.invoke(captureArgsBuilder);
        Method createSyncCaptureListenerMethod = screenCaptureClass.getMethod("createSyncCaptureListener");
        Object syncScreenCapture = createSyncCaptureListenerMethod.invoke(null);
        Method captureDisplayMethod = windowManager.getClass().getMethod("captureDisplay", int.class, captureArgsClass, screenCaptureListenerClass);
        captureDisplayMethod.invoke(windowManager, defaultDisplay.getDisplayId(), captureArgs, syncScreenCapture);
        Method getBufferMethod = synchronousScreenCaptureListenerClass.getMethod("getBuffer");
        Object buffer = getBufferMethod.invoke(syncScreenCapture);
        if (buffer != null) {
            Method asBitmapMethod = screenshotHardwareBufferClass.getMethod("asBitmap");
            bmp = (Bitmap) asBitmapMethod.invoke(buffer);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return bmp;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java--包,访问修饰符,多态数组,==和equals,hashcode,toString

包 同一个包里面不能有重复的类&#xff0c;不同的包可以有相同的类&#xff0c;包和包之间互不干涉。一个包下面有很多的类。 包的命名规则&#xff1a; 只能包含数字&#xff0c;字母&#xff0c;下划线&#xff0c;小圆点&#xff0c;但不能用数字开头&#xff0c;不能是关…

Databend 开源社区上榜 2023 年度 OSCHINA 优秀开源技术团队

2023 年 12 月 8 日&#xff0c;OSCHINA 对其平台上众多认证的官方技术团队和开源社区进行了全面评估&#xff0c;并颁发了“ 2023 年度优秀开源技术团队”奖项&#xff0c;以表彰各团队在推动中国开源生态系统发展方面所展现的创新能力和显著贡献。 在这一评选中&#xff0c;…

【开源软件】2022年最佳开源软件-排名第一:AlmaLinux

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

网络编程 DAY6 作业

1.使用数据库创建一个工人信息库&#xff0c;包含工号&#xff08;主键&#xff09;、姓名、年龄、薪资 2.添加三条工人信息&#xff08;可以完整信息&#xff0c;也可以非完整信息&#xff09; 3.修改某一个人的薪资&#xff08;确定的一个&#xff09; 4.展示出工资在10000到…

C++ Qt开发:StringListModel字符串列表映射组件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍QStringListModel字符串映射组件的常用方法及…

智慧工地一体化云平台APP源码:监管端、工地端、危大工程、智慧大屏、物联网、塔机、吊钩、升降机

智慧工地管理平台是依托物联网、互联网建立的大数据管理平台&#xff0c;是一种全新的管理模式&#xff0c;能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。 智慧工地源码技术说明 1.微服务架构JavaSpring Cloud UniApp MySql 2.支持多端展示&#xff08;PC端、手…

istio 认证:对等身份认证+服务请求认证

istio 中有两种不同的身份认证方式&#xff1a; 基于 mTLS 的对等身份认证 PeerAuthentication基于 JWT&#xff08;JSON Web Token&#xff09;令牌的服务请求认证 RequestAuthentication 对等身份认证 PeerAuthentication 概念 提供服务到服务的认证服务网格的主要场景就…

循环神经网络中的梯度消失或梯度爆炸问题产生原因分析

循环神经网络中&#xff0c;通过时间反向传播&#xff08;backpropagation through time&#xff0c;BPTT&#xff09;实际上是循环神经网络中反向传播技术的一个特定应用。 &#xff08;1&#xff09;它要求我们将循环神经网络的计算图以此展开一个时间步&#xff0c;以获得模…

Redis BitMap(位图)

这里是小咸鱼的技术窝&#xff08;CSDN板块&#xff09;&#xff0c;我又开卷了 之前经手的项目运行了10多年&#xff0c;基于重构&#xff0c;里面有要实现一些诸如签到的需求&#xff0c;以及日历图的展示&#xff0c;可以用将签到信息存到传统的关系型数据库&#xff08;MyS…

BBS项目--登录

BBS阶段性测试总要求 django登录报错 Error: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。 原因分析&#xff1a;出现这种情况在Windows中很常见&#xff0c;就是端口被占用 解决措施&#xff1a;这时我们只需改一下端口便可以了 登录前端页面(HTML…

网络技术基础与计算思维实验教程_3.2_无线局域网与以太网互连实验

实验内容 实验目的 实验原理 实验步骤 打开上一个实验的文件 切换到物理工作区 导航到城市家园 放置一台交换机 和两台台式机 直通线连接 把AP0链接到交换机的端口3上 切换回逻辑工作区 选择DHCP自动获取网络信息 PC1同样 然后 验证通信过程 laptop0和PC0 laptop1和PC1 验…

AcWing算法进阶课-1.1.2Dinic/ISAP求最大流

算法进阶课整理 CSDN个人主页&#xff1a;更好的阅读体验 原题链接 题目描述 给定一个包含 n n n 个点 m m m 条边的有向图&#xff0c;并给定每条边的容量&#xff0c;边的容量非负。 图中可能存在重边和自环。求从点 S S S 到点 T T T 的最大流。 输入格式 第一行包…

CentOS6.10 卸载MySQL8.0.34升级至8.0.35

准备要更新的MySQL安装包,下载地址:MySQL :: Download MySQL Community Server 查看当前MySQL版本 备份数据库 mysqldump -uroot -p -B > /opt/backup/20231220_mysql.sql 检查备份文件 查看所有服务项: service --status-all 可以看到我们注册的MySQL服务是mysqld 停止…

2023年中国数据智能管理峰会(DAMS上海站2023)-核心PPT资料下载

一、峰会简介 数据已经成为企业的核心竞争力&#xff01;谁掌控数据、更好的利用数据、实现资产化&#xff0c;谁就会真正率先进入大数据时代。 1、数据智能管理趋势和挑战 在峰会上&#xff0c;与会者讨论了数据智能管理的最新趋势和挑战。随着数据量的不断增加&#xff0c…

FMCW雷达仿真:基于L形阵列4D点云获取

摘要&#xff1a;本期内容为3D点云目标获取的延续工作&#xff0c;在距离、速度、方位角估计的基础上&#xff0c;通过设计L型阵列结构&#xff0c;进一步实现目标俯仰角的估计&#xff0c;最终实现目标4-D点云的获取。首先&#xff0c;通过中频信号建立仿真信号模型&#xff0…

【Chrome】ERR_SSL_PROTOCOL_ERROR问题

文章目录 前言一、下载二、使用步骤总结 前言 Edge升级最新版后&#xff0c;有的https访问不了&#xff0c;报如下错误 发现新版Chrome以及Chromium内核访问nginx ssl时报错&#xff0c;顺着这个思路接着查看到大佬的结论&#xff1a;服务器nginx使用的openssl版本过低&#…

MyBatis关联查询(一、一对一查询)

MyBatis关联查询&#xff08;一、一对一查询&#xff09; 需求&#xff1a;查询账户信息&#xff0c;关联查询用户信息。 分析&#xff1a;因为一个账户信息只能供某个用户使用&#xff0c;所以从查询账户信息出发关联查询用户信息为一对一查询。 在第一个mybatis项目并读取数…

【网络编程】poll和epoll服务器的设计

文章目录 前言一、poll二、epoll 1.epoll初识2.epoll服务器的设计3.epoll的工作原理4.epoll的优点5.epoll的工作模式总结 前言 poll和select一样&#xff0c;也是一种linux中的多路转接的方案。而poll解决了select的两个问题&#xff1a; 1.select的文件描述符有上限的问题。…

[计网02] 数据链路层 笔记 总结 详解

目录 数据链路层概述 主要功能 封装成帧 透明传输 差错检测 冗余码 差错控制 检错编码 纠错编码 奇偶效验法 CRC循环冗余码 静态分配信道 频分多路复用FDM 时分多路复用TDM 波分多路复用WDM 码分多路复用CDM 随机访问介质的访问控制 ALOHA CSMA CSMA/CD CSMA/…

Weblogic Server工具WLST的使用

1.Weblogic脚本工具WLST介绍 可以用命令行来操作 Weblogic scripting tools 2.Weblogic WLST三种工作模式 2.1 wlst.sh tips:weblogic的T3 协议与HTTP/HTTPS 协议 操作如下&#xff1a;wlst在 common目录下 weblogic14c/wlserver/common/bin/ [weblogicfysedu32 weblogic]$…