当前位置: 首页 > news >正文

Netty Review - Netty与Protostuff:打造高效的网络通信

文章目录

  • 概念
  • Pre
  • Pom
  • Server & Client
  • ProtostuffUtil 解读
  • 测试
  • 小结

在这里插入图片描述


概念

在这里插入图片描述


Pre

每日一博 - Protobuf vs. Protostuff:性能、易用性和适用场景分析


Pom

    	<dependency><groupId>com.dyuproject.protostuff</groupId><artifactId>protostuff-api</artifactId><version>1.2.2</version></dependency><dependency><groupId>com.dyuproject.protostuff</groupId><artifactId>protostuff-core</artifactId><version>1.2.2</version></dependency><dependency><groupId>com.dyuproject.protostuff</groupId><artifactId>protostuff-runtime</artifactId><version>1.2.2</version></dependency>

Server & Client

package com.artisan.codec.protostuff;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
// 定义Netty服务器类
public class NettyServer {// main方法为程序入口点public static void main(String[] args) throws Exception {// 创建主从线程组,用于处理Netty的事件循环EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup();try {// 创建ServerBootstrap实例,用于设置服务器参数ServerBootstrap serverBootstrap = new ServerBootstrap();// 配置服务器线程组serverBootstrap.group(bossGroup, workerGroup)// 设置使用的Channel类型.channel(NioServerSocketChannel.class)// 设置Channel初始化处理器.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 获取Channel的PipelineChannelPipeline pipeline = ch.pipeline();// 添加自定义的处理器pipeline.addLast(new NettyServerHandler());}});// 打印启动信息System.out.println("netty server start。。");// 绑定端口并启动服务器ChannelFuture channelFuture = serverBootstrap.bind(9876).sync();// 等待服务器Channel关闭channelFuture.channel().closeFuture().sync();} finally {// 优雅地关闭主从线程组bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}

这段代码首先设置了两个EventLoopGroup,一个用于接受连接(boss),另一个用于处理已接受连接的IO操作(worker)。然后创建了一个ServerBootstrap实例来配置和启动服务器。在ServerBootstrap中指定了使用的EventLoopGroupChannel类型以及子Channel的初始化处理器。初始化处理器中添加了一个自定义的NettyServerHandler,这应该是处理网络事件和业务逻辑的地方。

服务器启动后,会绑定到本地端口9876,并等待连接。程序最后会优雅地关闭线程组,释放资源。

需要注意的是,这段代码缺少了NettyServerHandler类的定义,这应该是处理网络事件和业务逻辑的具体实现。同时,这段代码没有异常处理和资源管理的健壮性考虑,例如可能需要捕获并处理Exception等。


NettyServerHandler的类,该类继承了ChannelInboundHandlerAdapter,表示一个自定义的Netty通道入站处理器。处理器中重写了channelReadexceptionCaught方法,分别用于处理通道读取事件和异常事件。

在这里插入图片描述

package com.artisan.codec.protostuff;
// 引入Netty相关类
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
// 定义Netty服务器处理器类
public class NettyServerHandler extends ChannelInboundHandlerAdapter {// 重写channelRead方法,处理通道读取事件@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 获取客户端发送的ByteBuf数据ByteBuf buf = (ByteBuf) msg;// 将ByteBuf数据转换为字节数组byte[] bytes = new byte[buf.readableBytes()];buf.readBytes(bytes);// 使用ProtostuffUtil工具类对字节数组进行反序列化操作System.out.println("从客户端读取到Object:" + ProtostuffUtil.deserializer(bytes, Artisan.class));}// 重写exceptionCaught方法,处理异常事件@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {// 打印异常堆栈信息cause.printStackTrace();// 关闭通道ctx.close();}
}

channelRead方法中,当通道读取到数据时,会将接收到的ByteBuf对象转换为字节数组,并使用ProtostuffUtil工具类的deserializer方法进行反序列化操作,将字节数组还原为Artisan对象。Artisan类是客户端发送的数据对应的Java对象。

exceptionCaught方法中,当发生异常时,会打印异常堆栈信息,并关闭通道。这有助于及时发现并处理异常,避免程序出现异常无法处理的情况。


这段代码是一个使用Netty框架的简单客户端程序。客户端程序的主要作用是连接到服务器,并发送或接收数据。下面是对这段代码的解读和增加的中文注释:

package com.artisan.codec.protostuff;
// 引入Netty相关类
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
// 定义Netty客户端类
public class NettyClient {// main方法为程序入口点public static void main(String[] args) throws Exception {// 创建事件循环组EventLoopGroup group = new NioEventLoopGroup();try {// 创建Bootstrap实例,用于设置客户端参数Bootstrap bootstrap = new Bootstrap();// 配置客户端事件循环组bootstrap.group(group).channel(NioSocketChannel.class)// 设置客户端Channel初始化处理器.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 获取Channel的PipelineChannelPipeline pipeline = ch.pipeline();// 添加自定义的处理器pipeline.addLast(new NettyClientHandler());}});// 打印启动信息System.out.println("netty client start。。");// 连接到服务器ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9876).sync();// 等待客户端Channel关闭channelFuture.channel().closeFuture().sync();} finally {// 优雅地关闭事件循环组group.shutdownGracefully();}}
}

这段代码首先创建了一个NioEventLoopGroup,用于处理Netty的事件循环。然后创建了一个Bootstrap实例来配置和启动客户端。在Bootstrap中指定了使用的事件循环组、Channel类型以及子Channel的初始化处理器。初始化处理器中添加了一个自定义的NettyClientHandler,这是处理网络事件和业务逻辑的地方。

客户端启动后,会连接到服务器127.0.0.1的端口9876。程序最后会优雅地关闭事件循环组,释放资源。


NettyClientHandler的类,该类继承了ChannelInboundHandlerAdapter,表示一个自定义的Netty通道入站处理器。处理器中重写了channelReadchannelActive方法,分别用于处理通道读取事件和通道激活事件。

在这里插入图片描述

package com.artisan.codec.protostuff;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.util.Arrays;
/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
// 定义Netty客户端处理器类
public class NettyClientHandler extends ChannelInboundHandlerAdapter {// 重写channelRead方法,处理通道读取事件@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 打印服务器发送的消息System.out.println("收到服务器消息:" + msg);}// 重写channelActive方法,处理通道激活事件@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {// 打印客户端处理器发送数据信息System.out.println("NettyClientHandler发送数据");// 使用ProtostuffUtil工具类对对象进行序列化操作Artisan artisan = new Artisan(1, "artisan", new Address("xx", Arrays.asList("code", "run")));ByteBuf buf = Unpooled.copiedBuffer(ProtostuffUtil.serializer(artisan));// 向服务器发送序列化后的数据ctx.writeAndFlush(buf);}
}

这段代码定义了一个名为NettyClientHandler的Netty通道入站处理器,主要用于处理通道读取事件和通道激活事件。具体功能如下:

  1. 重写channelRead方法:当通道读取到数据时,该方法会被调用,并打印服务器发送的消息。
  2. 重写channelActive方法:当通道激活时(即成功连接到服务器),该方法会被调用。在该方法中,使用ProtostuffUtil工具类对Artisan对象进行序列化操作,并将序列化后的数据发送给服务器。

注意:在实际使用中,建议在channelActive方法最后添加buf.release();来释放ByteBuf对象,避免内存泄漏。


package com.artisan.codec.protostuff;import java.io.Serializable;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class Artisan implements Serializable {private int id;private String name;private Address address;public Artisan() {}public Artisan(int id, String name) {super();this.id = id;this.name = name;}public Artisan(int id, String name, Address address) {this.id = id;this.name = name;this.address = address;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}@Overridepublic String toString() {return "Artisan{" +"id=" + id +", name='" + name + '\'' +", address=" + address +'}';}
}
package com.artisan.codec.protostuff;import java.util.List;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class Address {private String location;private List<String> hobbies;public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public List<String> getHobbiies() {return hobbies;}public void setHobbies(List<String> hobbies) {this.hobbies = hobbies;}public Address() {}public Address(String location) {this.location = location;}public Address(String location, List<String> hobbies) {this.location = location;this.hobbies = hobbies;}@Overridepublic String toString() {return "Address{" +"location='" + location + '\'' +", hobbies=" + hobbies +'}';}
}

ProtostuffUtil 解读

package com.artisan.codec.protostuff;import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world* @desc: protostuff 序列化工具类,基于protobuf封装*/
public class ProtostuffUtil {// 使用ConcurrentHashMap缓存Schema,提高性能private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<Class<?>, Schema<?>>(); // 定义一个ConcurrentHashMap,用于缓存Schema// 获取类的Schema,如果缓存中没有则创建一个新的Schema并缓存起来private static <T> Schema<T> getSchema(Class<T> clazz) { // 定义一个泛型方法,用于获取类的SchemaSchema<T> schema = (Schema<T>) cachedSchema.get(clazz); // 从缓存中获取Schemaif (schema == null) { // 如果Schema为空schema = RuntimeSchema.getSchema(clazz); // 创建一个新的Schemaif (schema != null) { // 如果新的Schema不为空cachedSchema.put(clazz, schema); // 将新的Schema添加到缓存中}}return schema; // 返回Schema}/*** 序列化** @param obj 要序列化的对象* @return 序列化后的字节流*/public static <T> byte[] serializer(T obj) { // 定义一个泛型方法,用于序列化对象@SuppressWarnings("unchecked")Class<T> clazz = (Class<T>) obj.getClass(); // 获取对象的类类型LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); // 分配一个LinkedBuffer缓冲区try {Schema<T> schema = getSchema(clazz); // 获取对象的Schemareturn ProtostuffIOUtil.toByteArray(obj, schema, buffer); // 将对象序列化为字节流} catch (Exception e) {throw new IllegalStateException(e.getMessage(), e); // 如果出现异常,则抛出自定义异常} finally {buffer.clear(); // 清理LinkedBuffer缓冲区}}/*** 反序列化** @param data  序列化的字节流* @param clazz 对象的类类型* @return 反序列化后的对象*/public static <T> T deserializer(byte[] data, Class<T> clazz) { // 定义一个泛型方法,用于反序列化字节流try {T obj = clazz.newInstance(); // 创建一个新的对象实例Schema<T> schema = getSchema(clazz); // 获取对象的SchemaProtostuffIOUtil.mergeFrom(data, obj, schema); // 将字节流反序列化为对象return obj; // 返回反序列化后的对象} catch (Exception e) {throw new IllegalStateException(e.getMessage(), e); // 如果出现异常,则抛出自定义异常}}public static void main(String[] args) {byte[] userBytes = ProtostuffUtil.serializer(new Artisan(1, "artisan", new Address("ssss", Arrays.asList("code", "run"))));Artisan artisan = ProtostuffUtil.deserializer(userBytes, Artisan.class);System.out.println(artisan);}
}

ProtostuffUtil提供了对Google的Protocol Buffers(protobuf)序列化格式的封装。该工具类使用com.dyuproject.protostuff库,这是一个Google protobuf的Java扩展库,提供了更简单、更灵活的API。

  1. 缓存Schema: ProtostuffUtil使用一个ConcurrentHashMap来缓存不同类的Schema。这样做可以避免在每次序列化或反序列化时都创建新的Schema,从而提高性能。

    private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();
    
  2. 获取Schema: 工具类提供了一个泛型方法getSchema(Class<T> clazz)来获取某个类的Schema。如果Schema已经在缓存中,就直接返回;否则,创建一个新的Schema并将其添加到缓存中。

    private static <T> Schema<T> getSchema(Class<T> clazz) {Schema<T> schema = cachedSchema.get(clazz);if (schema == null) {schema = RuntimeSchema.getSchema(clazz);if (schema != null) {cachedSchema.put(clazz, schema);}}return schema;
    }
    
  3. 序列化: serializer(T obj)方法用于将对象序列化为字节流。这个方法使用ProtostuffIOUtil.toByteArray方法完成序列化,并返回序列化后的字节流。

    public static <T> byte[] serializer(T obj) {@SuppressWarnings("unchecked")Class<T> clazz = (Class<T>) obj.getClass();LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);try {Schema<T> schema = getSchema(clazz);return ProtostuffIOUtil.toByteArray(obj, schema, buffer);} catch (Exception e) {throw new IllegalStateException(e.getMessage(), e);} finally {buffer.clear();}
    }
    
  4. 反序列化: deserializer(byte[] data, Class<T> clazz)方法用于将字节流反序列化为对象。这个方法使用ProtostuffIOUtil.mergeFrom方法完成反序列化,并返回反序列化后的对象。

    public static <T> T deserializer(byte[] data, Class<T> clazz) {try {T obj = clazz.newInstance();Schema<T> schema = getSchema(clazz);ProtostuffIOUtil.mergeFrom(data, obj, schema);return obj;} catch (Exception e) {throw new IllegalStateException(e.getMessage(), e);}
    }
    

总体而言,该工具类简化了protobuf的序列化和反序列化操作,并提供了Schema的缓存机制以提高性能。


测试

启动Server和Client后

在这里插入图片描述


小结

Protostuff是一个用于Java对象的序列化和反序列化的库,它的主要特点和功能如下:

  1. 高性能:Protostuff的序列化和反序列化操作非常快,对于大量数据的处理具有较高的性能优势。
  2. 简单易用:Protostuff的API设计简单明了,使用起来非常方便,可以快速实现对象的序列化和反序列化操作。
  3. 可扩展性:Protostuff允许用户自定义序列化和反序列化的逻辑,提供了丰富的扩展点,满足不同场景的需求。

总的来说,Protostuff是一个高效、简单、可扩展的Java序列化库,适用于多种场景,特别是对于大量数据和高性能要求的应用场景有较好的表现。

在这里插入图片描述

相关文章:

Netty Review - Netty与Protostuff:打造高效的网络通信

文章目录 概念PrePomServer & ClientProtostuffUtil 解读测试小结 概念 Pre 每日一博 - Protobuf vs. Protostuff&#xff1a;性能、易用性和适用场景分析 Pom <dependency><groupId>com.dyuproject.protostuff</groupId><artifactId>protostuff-…...

在ClickHouse数据库中启用预测功能

在这篇博文中&#xff0c;我们将介绍如何将机器学习支持的预测功能与 ClickHouse 数据库集成。ClickHouse 是一个快速、开源、面向列的 SQL 数据库&#xff0c;对于数据分析和实时分析非常有用。该项目由 ClickHouse&#xff0c; Inc. 维护和支持。我们将探索它在需要数据准备以…...

目标检测YOLO实战应用案例100讲-树上果实识别与跟踪计数(续)

目录 3.2 损失函数优化 3.3 实验过程 3.3.1 果实图像采集 3.3.2 数据扩增...

Docker 文件和卷 权限拒绝

一 创作背景 再复制Docker影像文件或访问Docker容器内已安装卷上的文件时我们常常会遇到&#xff1a;“权限被拒绝”的错误&#xff0c;在此&#xff0c;您将了解到为什么会出现“权限被拒绝”的错误以及如何解决这个问题。 二 目的 在深入探讨 Docker 容器中的 Permission De…...

Appium Server 启动失败常见原因及解决办法

Error: listen EADDRINUSE: address already in use 0.0.0.0:4723 如下图&#xff1a; 错误原因&#xff1a;Appium 默认的4723端口被占用 解决办法&#xff1a; 出现该提示&#xff0c;有可能是 Appium Server 已启动&#xff0c;关闭已经启动的 Appium Server 即可。472…...

将Abp默认事件总线改造为分布式事件总线

文章目录 原理创建分布式事件总线实现自动订阅和事件转发 使用启动Redis服务配置传递Abp默认事件传递自定义事件 项目地址 原理 本地事件总线是通过Ioc容器来实现的。 IEventBus接口定义了事件总线的基本功能&#xff0c;如注册事件、取消注册事件、触发事件等。 Abp.Events…...

Jupyter Notebook修改默认工作目录

1、参考修改Jupyter Notebook的默认工作目录_jupyter文件路径-CSDN博客修改配置文件 2.在上述博客内容的基础上&#xff0c;这里不是删除【%USERPROFILE%】而是把这个地方替换为所要设置的工作目录路径&#xff0c; 3.【起始位置】也可以更改为所要设置的工作目录路径&#x…...

高校/企业如何去做数据挖掘呢?

随着近年来人工智能及大数据、云计算进入爆发时期&#xff0c;依托三者进行的数据分析、数据挖掘服务已逐渐成为各行业进行产业升级的载体&#xff0c;缓慢渗透进我们的工作和生活&#xff0c;成为新时代升级版的智能“大案牍术”。 那么对于多数企业来说&#xff0c;如何做数据…...

数据仓库-数据治理小厂实践

一、简介 数据治理贯穿数仓中数据的整个生命周期&#xff0c;从数据的产生、加载、清洗、计算&#xff0c;再到数据展示、应用&#xff0c;每个阶段都需要对数据进行治理&#xff0c;像有些比较大的企业都是有自己的数据治理平台或者会开发一些便捷的平台&#xff0c;对于没有平…...

【C++多线程编程】(五)之 线程生命周期管理join() 与 detach()

在C中&#xff0c;std::thread 类用于创建和管理线程。std::thread 提供了两种主要的方法来控制线程的生命周期&#xff1a;join 和 detach。 detach方式&#xff0c;启动的线程自主在后台运行&#xff0c;当前的代码继续往下执行&#xff0c;不等待新线程结束。join方式&…...

金融信贷场景的风险“要素”与主要“风险点”

目录 要素一:贷款对象 风险点1:为不具备主体资格或主体资格有瑕疵的借款人发放贷款 风险表现: 防控措施: 风险点2:向国家限控行业发放贷款 风险表现: 防控措施: 风险点3:受理不符合准入条件的客户申请 风险表现: 防控措施: 要素二:金额 风险点4:过渡授…...

ubuntu下docker安装,配置python运行环境

参考自: 1.最详细ubuntu安装docker教程 2.使用docker搭建python环境 首先假设已经安装了docker&#xff0c;卸载原来的docker 在命令行中运行&#xff1a; sudo apt-get updatesudo apt-get remove docker docker-engine docker.io containerd runc 安装docker依赖 apt-get…...

在Docker中安装kafka遇到问题记录

命令含义解答&#xff1a; 在docker安装kafka的时候&#xff0c;启动kafka的时候会执行下面语句&#xff1a; docker run -d --log-driver json-file --log-opt max-size100m --log-opt max-file2 --name kafka -p 9092:9092 -e KAFKA_BROKER_ID0 -e KAFKA_ZOOKEEPER_CONNEC…...

aws-waf-cdn 基于规则组的永黑解决方案

1. 新建waf 规则组 2. 为规则组添加规则 根据需求创建不同的规则 3. waf中附加规则组 &#xff08;此时规则组所有规则都会附加到waf中&#xff0c;但是不会永黑&#xff09; 此刻&#xff0c;可以选择测试下规则是否生效&#xff0c;测试前确认保护资源绑定无误 4. 创建堆…...

如何实现免费无限流量云同步笔记软件Obsidian?

目录 前言 如何实现免费无限流量云同步笔记软件Obsidian&#xff1f; 一、简介 软件特色演示&#xff1a; 二、使用免费群晖虚拟机搭建群晖Synology Drive服务&#xff0c;实现局域网同步 1 安装并设置Synology Drive套件 2 局域网内同步文件测试 三、内网穿透群晖Synol…...

GPTs | Actions应用案例

上篇文章说道&#xff0c;如何使用创建的GPTs通过API接口去获取外部的一些信息&#xff0c;然后把获取的外部信息返回给ChatGPT让它加工出来&#xff0c;回答你的问题&#xff0c;今天我们就来做一个通俗易懂的小案例&#xff0c;让大家来初步了解一下它的使用法&#xff01; …...

Python Opencv实践 - 手势音量控制

本文基于前面的手部跟踪功能做一个手势音量控制功能&#xff0c;代码用到了前面手部跟踪封装的HandDetector.这篇文章在这里&#xff1a; Python Opencv实践 - 手部跟踪-CSDN博客文章浏览阅读626次&#xff0c;点赞11次&#xff0c;收藏7次。使用mediapipe库做手部的实时跟踪&…...

关于Selenium的网页对象单元测试的设计模式

写在前面&#xff1a;经过了实践总结一下经验&#xff0c;心得进行一个分享。 首先driver是可以单独抽出来的&#xff0c;变成一个driver函数放在driver.py。 from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver…...

基于多反应堆的高并发服务器【C/C++/Reactor】(上)

&#xff08;一&#xff09;初始化服务器端用于监听的套接字 Server.h #pragma once // 初始化监听的套接字 int initListenFd(unsigned short port); Server.c int initListenFd(unsigned short port) {// 1.创建监听的fdint lfd socket(AF_INET, SOCK_STREAM, 0);if(lf…...

腾讯云debian服务器的连接与初始化

目录 1. 远程连接2. 软件下载3. 设置开机自启动 1. 远程连接 腾讯云给的服务器在安装好系统之后&#xff0c;只需要在防火墙里面添加一个白名单&#xff08;ip 或者域名&#xff09;就能访问了。 浏览器打开https://www.ipip.net/&#xff0c;在左下角找到自己所用的WIFI的公…...

如何快速构建智能图像篡改检测系统:3步实战指南

如何快速构建智能图像篡改检测系统&#xff1a;3步实战指南 【免费下载链接】image_tampering_detection_references A list of papers, codes and other interesting collections pertaining to image tampering detection and localization. 项目地址: https://gitcode.com…...

Brush 3D 重建引擎:多系统兼容、功能强大,渲染训练速度比 gsplat 更快!

特性训练方面&#xff0c;Brush 可接受 COLMAP 数据或 Nerfstudio 格式的数据集&#xff0c;在本地、移动端和浏览器中都能完全支持训练。训练时可与场景交互&#xff0c;实时查看训练动态&#xff0c;对比渲染效果与输入视图&#xff0c;还支持对带透明度的图像进行遮罩处理。…...

AI编程再突破:文心快码发布行业首个多模态、多智能体协同Comate AI IDE

前言 2025年6月23日&#xff08;图灵诞辰日&#xff09;&#xff0c;百度在AI开放日正式发布文心快码Comate AI IDE&#xff0c;这是全球首个深度融合多模态感知与多智能体协同能力的独立AI原生开发环境。它彻底打破了传统AI编程工具"单线程补全、黑盒式生成"的局限&…...

拉罗替尼Larotrectinib常见副作用ALT升高及疲劳如何有效应对【海得康】

在拉罗替尼&#xff08;Larotrectinib&#xff09;治疗NTRK融合阳性实体瘤的临床实践中&#xff0c;ALT升高与疲劳堪称两大最具代表性的不良反应。前者直指肝脏安全底线&#xff0c;后者则如影随形地侵蚀着患者的日常功能与生活质量。根据FDA批准的处方信息、三项关键临床试验&…...

昆仑芯天池256卡超节点上个月点亮,将于6月正式上市

雷递网 乐天 5月13日5月13日&#xff0c;在Create2026百度AI开发者大会上&#xff0c;百度创始人李彦宏首次提出AI时代的“度量衡”——日活智能体数&#xff08;DAA&#xff09;。他认为&#xff0c;进入智能体时代&#xff0c;衡量一个平台和生态的繁荣&#xff0c;更应该关注…...

从课堂作业到项目复盘:用Proteus仿真四人抢答器,我踩过的那些‘坑’

从课堂作业到项目复盘&#xff1a;用Proteus仿真四人抢答器&#xff0c;我踩过的那些‘坑’ 第一次在Proteus里搭建四人抢答器时&#xff0c;我以为只要按教科书上的电路图连线就能轻松完成。直到LED灯在上电瞬间诡异地闪烁、计数器在临界值跳变时卡死、抢答信号被误判为违规……...

深度解析智能歌词同步工具:macOS用户的革命性解决方案

深度解析智能歌词同步工具&#xff1a;macOS用户的革命性解决方案 【免费下载链接】LyricsX &#x1f3b6; Ultimate lyrics app for macOS. 项目地址: https://gitcode.com/gh_mirrors/ly/LyricsX LyricsX是一款专为macOS设计的智能歌词同步工具&#xff0c;它彻底改变…...

Python统一调用多款AI大模型:python-tgpt库实战指南

1. 项目概述&#xff1a;一个让Python与AI对话更简单的工具如果你最近在尝试用Python调用各种大语言模型&#xff08;LLM&#xff09;的API&#xff0c;比如OpenAI的GPT、Google的Gemini&#xff0c;或者开源的Llama、Mistral&#xff0c;那你大概率经历过这样的场景&#xff1…...

FPGA高速收发器CDR模块深度解析:从NRZ码中“捞出”时钟的RXOUTCLKPMA是怎么工作的?

FPGA高速收发器CDR模块技术探秘&#xff1a;解码NRZ数据中的时钟玄机 在高速数字通信系统中&#xff0c;时钟数据恢复&#xff08;CDR&#xff09;技术如同一位技艺精湛的侦探&#xff0c;能够从看似杂乱无章的NRZ&#xff08;非归零码&#xff09;数据流中&#xff0c;精准地&…...

usehooks-ts:React Hooks工具集,提升开发效率与代码质量

1. 项目概述&#xff1a;一个现代React Hooks的“瑞士军刀”如果你正在用React做项目&#xff0c;尤其是TypeScript项目&#xff0c;那么你大概率经历过这样的场景&#xff1a;为了一个简单的“防抖”功能&#xff0c;去网上搜一段代码&#xff0c;复制粘贴&#xff0c;然后发现…...