【JavaEE】网络编程socket

1.❤️❤️前言~🥳🎉🎉🎉

Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。

如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的内容感兴趣,记得关注我👀👀以便不错过每一篇精彩。

当然,如果在阅读中发现任何问题或疑问,我非常欢迎你在评论区留言指正🗨️🗨️。让我们共同努力,一起进步!

加油,一起CHIN UP!💪💪

🔗个人主页:E绵绵的博客
📚所属专栏:

1. JAVA知识点专栏

        深入探索JAVA的核心概念与技术细节

2.JAVA题目练习

        实战演练,巩固JAVA编程技能

3.c语言知识点专栏

        揭示c语言的底层逻辑与高级特性

4.c语言题目练习

        挑战自我,提升c语言编程能力

5.Mysql数据库专栏

        了解Mysql知识点,提升数据库管理能力

6.html5知识点专栏

        学习前端知识,更好的运用它

7. css3知识点专栏

        在学习html5的基础上更加熟练运用前端

8.JavaScript专栏

        在学习html5和css3的基础上使我们的前端使用更高级、

9.JavaEE专栏

        学习更高阶的Java知识,让你做出网站

📘 持续更新中,敬请期待❤️❤️

2.简单理解socket 

 之前提过在网络编程中,应用层到运输层需要显式调用 API,而运输层到网络层以及后续层的通信通常是自动处理的,不需要开发者主动调用 API,反过来也是同理。

这里显示调用的API就是socket(套接字) ,只有调用了它,数据才能运输成功。

由于传输层提供了两个最核心的协议:UDP TCP。
因此,socket api 中也提供了两种风格来面对UDP和TCP。(传输层用哪种协议就用哪种风格去应对)

对于socket 不仅是个API,本质上是一种特殊的文件.Socket 就属于是把"网卡"这个设备,给抽象成了文件了往 socket 文件中写数据,就相当于通过网卡发送数据.从 socket 文件读数据,就相当于通过网卡接受数据 

 3.TCP和UDP的差别(初识)

首先在了解socket用两种风格去面对UDP和TCP时,我们还要先知道udp和tcp的区别:


TCP的特点:

有连接
可靠传输
面向字节流
全双工


UDP的特点:

无连接
不可靠传输
面向数据报
全双工

连接:

此处说的"连接"不是物理意义的连接,而是抽象,虚拟的连接。

计算机中,这种 抽象 的连接是很常见的,此处的连接本质上就是建立连接的双方,各自保存对方的信息,两台计算机建立连接,就是双方彼此保存了对方的关键信息(ip和端口)

所以这也意味着如果协议是tcp的话,必须要先建立好连接才能传输信息,如果是udp,就不用建立连接就能传输消息。


可靠传输/ 不可靠传输:
网络上存在的"异常情况"是非常多的,无论使用什么样的软硬件的技术手段无法100%保证网络数据能够从A一定传输到。此处谈到的"可靠传输",尽可能的完成数据传输。虽然无法确保数据到达对方,至少可以知道,当前这个数据对方是不是收到了。
此处谈到的可靠传输,主要指的是发的数据到没到,发送方能够清楚的感知到。


面向字节流/面向数据报
面向字节流:此处谈到的字节流和文件中的字节流完全一致—— TCP(网络中传输数据的基本单位就是字节)
面向数据报:udp每次传输的基本单位是一个数据报(由一系列的字节构成的),它是特定的结构(之前讲过)。


全双工/半双工:

全双工通信允许数据同时在两个方向上传输。这意味着通信双方可以同时发送和接收数据,而不会互相干扰。

半双工通信允许数据在两个方向上传输,但不能同时进行。通信双方只能交替地发送和接收数据。

这只是简单的讲述一下,后面讲网络原理会讲到更多的本质内容。 

4.socket面对udp 

udp时的socket相较于tcp,要相对简单,我们先讲这个 

DatagramSocket API

DatagramSocket 是UDP时的Socket,用于发送和接收UDP数据报。 

DatagramSocket 构造方法


DatagramSocket 方法:

DatagramPacket API 

DatagramPacket是UDP Socket发送和接收的数据报(UDP面向数据报,每次发送接收数据的基本单位,就是一个UDP数据报)


DatagramPacket 构造方法:

由于udp是没建立连接的,所以每次发送都要标明要发送的对方ip和端口。(如果建立了连接就不需要发送ip和端口)


DatagramPacket 方法:


构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创建。

实现回显服务器和客户端

注:这里编写的客户端服务器是一个简单 UDP 版本的服务器,称之为:回显服务器。

一个普通的服务器: 收到请求,根据请求计算响应(业务逻辑),返回响应。

回显服务器: 省略了普通服务器的 “根据请求计算响应”(这里的响应一般非常复杂),这里只是为了演示 socket api 的用法。

这里有一个重点要说下:

对于一个服务器来讲,我们需要让其绑定一个明确的端口号,因为在服务器在网络传输中处于一个被动的状态,没有一个明确的端口号,客户端就无法寻找到请求的服务器。

而对于一个客户端来说,我们可以让其随机分配一个端口号给他,不要指定,因为客户端是客户使用,不像我们程序员知道怎么分配端口,客户不清楚怎么分配端口,万一客户指定的端口被别人占用就会报错,它还不知道怎么修改,所以采用随机分配。(随机分配的都是没被占用的端口号)

以后的服务器客户端 端口号都遵循这规定

服务器端的逻辑如下:

  1. 创建套接字:创建一个 DatagramSocket 对象,并绑定到指定的端口(10003),用于接收和发送数据报。

  2. 接收数据报:在 while (true) 循环中,创建一个 DatagramPacket 对象,用于接收客户端发送的数据报。调用 datagramSocket.receive(datagramPacket) 方法等待并接收数据报。

  3. 处理数据:将接收到的数据报中的字节数组转换为字符串,然后调用 process 方法处理该字符串。在这个例子中,process 方法只是简单地返回传入的字符串本身。

  4. 发送响应:将处理后的字符串转换为字节数组,并创建一个新的 DatagramPacket 对象,包含要发送的数据、目标地址和端口(即客户端的地址和端口)。使用 datagramSocket.send(datagramPacket1) 方法将响应数据报发送回客户端。

  5. 循环处理:上述步骤在 while (true) 循环中不断重复,服务器持续等待接收新的数据报并响应,直到程序被手动终止。

public class Serve {public static void main(String[] args) throws IOException,InterruptedException {System.out.println("服务器上线");DatagramSocket datagramSocket=new DatagramSocket(10003);while(true){DatagramPacket datagramPacket=new DatagramPacket(new byte[4096],4096);datagramSocket.receive(datagramPacket);String string=new String(datagramPacket.getData(),0,datagramPacket.getLength());byte[] bytes1=process(string).getBytes();DatagramPacket datagramPacket1 = new DatagramPacket(bytes1,bytes1.length,new InetSocketAddress(datagramPacket.getAddress(),datagramPacket.getPort()));datagramSocket.send(datagramPacket1);}}public static String process(String string){return  string;}
}

客户端设计逻辑:

  1. 创建套接字:创建一个 DatagramSocket 对象,用于发送和接收数据报。这个套接字没有绑定到特定的端口,因此会使用一个临时端口。

  2. 读取用户输入:使用 Scanner 从控制台读取用户输入的字符串。

  3. 发送数据报

    • 将用户输入的字符串转换为字节数组。

    • 创建一个 DatagramPacket 对象,包含要发送的数据、目标地址和端口。

    • 使用 DatagramSocket 发送数据报。

  4. 接收响应

    • 创建一个 DatagramPacket 对象,用于接收服务器的响应。

    • 使用 DatagramSocket 接收数据报。

    • 将接收到的字节数组转换为字符串并打印到控制台。

  5. 循环处理:上述步骤在 while (true) 循环中不断重复,直到程序被手动终止。

public class Client {public static void main(String[] args) throws IOException {System.out.println("客户端启动");Scanner scanner=new Scanner(System.in);DatagramSocket datagramSocket=new DatagramSocket();while(true){String string=scanner.next();byte[] bytes=string.getBytes();DatagramPacket datagramPacket1 = new DatagramPacket(bytes,bytes.length,new InetSocketAddress("192.168.50.173",10003));datagramSocket.send(datagramPacket1);DatagramPacket datagramPacket=new DatagramPacket(new byte[4096],4096);datagramSocket.receive(datagramPacket);String string1=new String(datagramPacket.getData(),0,datagramPacket.getLength());System.out.println(string1);}}
}

对于这里我们要特殊说几个点:


1.对于字节数组内部存储数据报并不可能是全部都占用了,肯定有空闲空间,所以在将该字节数组变为字符串时我们肯定要把空闲空间给划掉,这时候就用datagrampacket.getlength ()得到有效长度,从而就可以忽略掉,否则会引发bug


2.仔细观察代码,发现该服务器可以同时支持多个客户端

这里有个疑问,一段代码为什么会能实现多个窗口呢?一般不是只能一段代码实现一个?这玩意我们是可以修改的。

通过这样修改,我们就能一段代码生成多个实例对象,多个窗口(客户端)。

3.对于该DatagramSocket虽然是文件,但是并不需要close,因为Datagramsocket是全程跟随该进程的,当进程结束时,我们才不会用DatagramSocket,进程只要还在运行,它依然还会用。该进程结束时文件描述表自然就销毁了,根本不用再添一个close。

5.socket面对tcp 

ServerSocket 

ServerSocket 是创建TCP服务端Socket的API。


ServerSocket 构造方法:


ServerSocket 方法:


因为tcp是有连接的,所以在一个客户端给服务器传输信息前,我们需要先建立连接,这样才能传输信息,这时候就需要用到servesocket了。


当创建好servesocket后,如果有客户端想和服务器建立连接,发送了连接请求,这个时候服务器的应用程序是不需要做出任何操作,由服务器的系统内核直接就完成了连接建立的流程(内部是三次握手从而建立连接,之后会讲),这样客户端和服务器之间建立了逻辑上的连接,这个连接在内核中以连接对象的形式存在。我们就将该连接对象放入已完成连接队列中(accept队列)。创建好的连接对象就会在该内核的队列中(这个队列是每个 serverSocket 都有一个这样的队列) 排队.
而该服务器要想和已经连接好的客户端进行通讯的话,还需要通过 accept函数从accept队列中取出连接对象,通过该对象就创建socket用于通信。

当我们accept时 如果连接对象在队列中不存在则会堵塞,有的话则会接受且创建一个socket对象用于通讯。我们可以认为上述的模型是一个生产者消费者模型。

socket 

Socket 可以是客户端Socket,也可以是服务器中通过连接对象建立的 Socket。 不管是客户端还是服务端的Socket,都是双方建立连接以后,用来双方进行通讯的工具


这个不仅是客户端的socket的构造方法,还是客户端的连接建立请求。


以下是它的普通方法

这里的输入流和输出流就是我们发送消息的工具,它们是普通的字节流,我们之前文件io里学到的所有方法在这里也全能用,通过该输入流读取数据就能读取到另一个主机发送的数据,同理输出流就往里面写数据就能发送到另一个主机的输入流里。

实现回显服务器和客户端            

这里实现的相比udp复杂一点

服务器端的逻辑如下:

  1. 服务器启动

    • 创建一个 ServerSocket 对象,绑定到指定的端口(10002),并监听客户端连接。

    • 打印 "服务器启动" 表示服务器已启动并正在等待客户端连接。

  2. 接受客户端连接

    • 调用 serverSocket.accept() 方法等待并接受客户端的连接请求。

    • 创建一个新的 Socket 对象,表示与客户端的连接。

  3. 处理客户端任务

    • 调用 startTask 方法处理客户端的请求。

    • startTask 方法中,获取客户端的输入流和输出流。

  4. 读取客户端请求并发送响应

    • 使用 Scanner 从输入流读取客户端发送的数据。

    • 使用 PrintWriter 向输出流发送响应数据。

    • 在循环中不断读取客户端发送的数据,直到 scanner.hasNext() 返回 false相当于客户端断开连接,之后会特殊说明这里的细节)。

    • 对于每次读取的数据,调用 process 方法进行处理(在这个例子中,process 方法只是简单地返回传入的字符串)。

    • 将处理后的字符串发送回客户端。

  5. 关闭连接

    • finally 块中关闭客户端套接字,确保资源被正确释放。

public class TcpServe {public static void main(String[] args) throws IOException {System.out.println("服务器启动");ServerSocket serverSocket = new ServerSocket(10002);Socket socket = serverSocket.accept();startTask(socket);}public static void startTask(Socket socket) throws IOException {try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {Scanner scanner = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);printWriter.flush();while (true) {if (!scanner.hasNext())break;String string = scanner.next();String string1 = process(string);printWriter.println(string1);printWriter.flush();}} catch (Exception e) {e.printStackTrace();} finally {socket.close();}}public static String process(String string) {return string;}}

客户端的逻辑如下:

  1. 客户端启动

    • 创建一个 Socket 对象,连接到指定的服务器地址(192.168.50.173)和端口(10002)。

    • 打印 "客户端上线" 表示客户端已启动并正在连接服务器。

  2. 获取输入输出流

    • 获取 Socket 对象的输入流和输出流,用于接收服务器的响应和发送客户端的请求。

  3. 读取用户输入并发送请求

    • 使用 Scanner 从控制台读取用户输入的字符串。

    • 使用 PrintWriter 将用户输入的字符串发送到服务器。

  4. 接收服务器响应

    • 使用 Scanner 从输入流读取服务器发送的响应。

    • 将服务器的响应打印到控制台。

  5. 循环处理

    • while (true) 循环中不断读取用户输入,发送请求,接收响应,直到程序被手动终止或出现异常。

  6. 关闭连接

    • finally 块中关闭客户端套接字,确保资源被正确释放。

public class TcpClient {public static void main(String[] args) throws IOException {System.out.println("客户端上线");Socket socket = new Socket("192.168.50.173", 10002);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {Scanner scanner = new Scanner(System.in);Scanner scanner1 = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);while (true) {String string = scanner.next();printWriter.println(string);printWriter.flush();System.out.println(scanner1.next());}} catch (Exception e) {e.printStackTrace();} finally {socket.close();}}
}

这样我们就实现了一个tcp通信:

但这里还是要说几个特殊的点:


1.这里由于我们采用的是printwrite,所以要用flush冲刷数据,否则可能有bug 


2.在 TCP 网络编程中,Scamner.hasHext() 方法的行为与它在处理本地输入(如控制台输入或文件输入)时的行为有所不同。

这里由于scanner是跟另一个主机的输出流联系在一块,所以没有明确的消息边界。因此,在执行Scanner.hasnext()时如果该输入流没数据那么该方法就会阻塞,直到输入流中有数据可用则返回出true。如果客户端断开了连接,连接的输出流则结束了,断开了连接,此时就有明确的消息边界,Scanmer.hasNext()方法就因为没数据会返回 false,所以退出。(有消息边界时没数据则返回false,有数据则返回true;没消息边界时没数据则堵塞,有数据则返回true,不可能返回false)


3.对于该程序,只支持单个客户端,不支持多个客户端,如果想要达到多个,则要用多线程。

public class TcpServe {public static void main(String[] args) throws IOException {System.out.println("服务器启动");ServerSocket serverSocket = new ServerSocket(10010);while (true) {Socket socket = serverSocket.accept();Thread thread = new Thread(() -> {try {TcpServe.startTask(socket);} catch (Exception e) {e.printStackTrace();}});thread.start();}}public static void startTask(Socket socket) throws IOException {try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {Scanner scanner = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);printWriter.flush();while (true) {if (!scanner.hasNext())break;String string = scanner.next();String string1 = process(string);printWriter.println(string1);printWriter.flush();}} catch (Exception e) {e.printStackTrace();} finally {socket.close();}}public static String process(String string) {return string;}}

如果我们程序线程创建销毁太频繁了,还可以用线程池,这样能提高效率

 
public class TcpServe {public static void main(String[] args) throws IOException {System.out.println("服务器启动");ServerSocket serverSocket = new ServerSocket(10017);ExecutorService executorService = Executors.newCachedThreadPool();while (true) {Socket socket = serverSocket.accept();executorService.submit(() -> {try {TcpServe.startTask(socket);} catch (Exception e) {e.printStackTrace();}});}}public static void startTask(Socket socket) throws IOException {try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {Scanner scanner = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);printWriter.flush();while (true) {if (!scanner.hasNext())break;String string = scanner.next();String string1 = process(string);printWriter.println(string1);printWriter.flush();}} catch (Exception e) {e.printStackTrace();} finally {socket.close();}}public static String process(String string) {return string;}}


4.对于socket以及它带的两个字节流文件我们都需要手动close,因为它们并不是全程跟随整个程序,有可能中途这些文件就不用了,所以就需要close对应的socket文件和字节流文件,否则一直不关而我们一直使用该程序,文件就会持续累积导致文件泄露问题。

而servesocket就不需要,因为它跟之前的Datagramsocket是全程跟随的,所以没必要多此一举。

对于这双方通信我们现在还是只限于一个主机内部,如果要两个主机进行交流就需要部署一个云服务器或者在一个局域网内部才能进行交流。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

超硬核区块链算法仿真:联盟链PBFT多线程仿真实现 :c语言完全详解版

1 22年年底想用gpt做出一个pbft的算法仿真,到了25年终于可以结合gpt grok perplexcity deepseek等实现了!!!!! 1.1简化版 // 定义 Windows 版本,确保条件变量相关函数可用 #define _WIN32_W…

【并发编程】聊聊forkJoin的原理和最佳实践

对于线程池来说,其实本质就是一个生产者消费者的模式,而通过竞争的方式从队列中获取任务执行。本质上其实就是按照任务级别进行处理,但是对于一些可以分而治之的任务,传统的线程池没有办法分治处理。一是无法对大任务进行拆分&…

【数据预测】基于遗传算法GA的LSTM光伏功率预测 GA-LSTM光伏功率预测【Matlab代码#91】

文章目录 【可更换其他算法,获取资源请见文章第6节:资源获取】1. 遗传算法GA2. 长短期记忆网络LSTM3. 基于GA-LSTM的光伏功率预测4. 部分代码展示5. 运行结果展示6. 资源获取 【可更换其他算法,获取资源请见文章第6节:资源获取】 …

Java 填充 PDF 模版

制作 PDF 模版 安装 OnlyOffice 从 OnlyOffice 官网下载 OnlyOffice Desktop,安装过程很简单,一路下一步即可。用 OnlyOffice 制作 PDF 模版(表单) 使用 OnlyOffice 表单设计器,制作表单,如下图 注意命名…

使用安装 Kettle 教程 Pentoho 10.2.0.0-222 安装 连接mysql

流程 准备下载安装测试链接常见问题 准备 需要提前安装好 JDK 配置好环境变量 (教程看前文) 安装好mysql(教程看前文) 下载好pentaho链接数据库驱动 下载pentaho安装包 https://pentaho.com/wp-content/uploads/2024/04/three-s…

MySQL表的增加、查询、修改、删除的基础操作

MySQL表的增加、查询、修改、删除的基础操作 一、CRUD二、新增数据 insert2.1 单行数据 全列插入2.2 多行数据 指定列插入 三、查询 select3.1 全列查询(select *)3.2 指定列查询3.3 表达式查询3.4 去重:distinct3.5 带有排序的查询&#x…

Windows Server 2025 使用 IIS 搭建 ASP.NET 3.5 网站

开启远程桌面 参考文章Windows server开启远程桌面教程打开服务管理器。ECS 配置安全组,开启 3389Telnet 验证网络联通性 telnet x.x.x.x 338安装 Windows App,登录验证 安装 ASP.NET 3.5 1.参考文章Windows Server 2012安装 .NET Framework 3.5和 Wi…

Linux上位机开发实战(能用的开发板计算资源)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 大家所能想到的嵌入式上位机开发,如果是linux,同时涉及到嵌入式的话,一般都会认为是把pc linux的软件port到板子…

STM32中断

中断的基本概念 中断具体定义:操作系统课程里有清晰的阐述。 STM32中断:中断来了,主程序都得立即暂停,程序由硬件电路自动跳转到中断程序中。中断执行前,进行现场保护;中断执行后,会再还原现场…

maven在windows系统上的详细安装和配置

下载 Maven 安装包 去官网下载,下载链接 下载到指定位置,解压,之后在该目录下新建一个文件夹 【repository】,作为本地仓库 Maven 的配置 配置本地仓库 ① 打开上一步新建的目录 repository, 复制路径 ② 打开 con…

如何为AI开发选择合适的服务器?

选择适合的服务器可以为您的AI项目带来更高的效率,确保最佳性能、可扩展性和可靠性,从而实现无缝的开发与部署。 选择适合的AI开发服务器可能并不容易。您需要一台能够处理大量计算和大型数据集的服务器,同时它还需要符合您的预算并易于管理…

OpenCV中的矩阵操作

OpenCV中的矩阵操作主要围绕Mat类展开,涵盖创建、访问、运算及变换等。 1. 创建矩阵 ‌零矩阵/单位矩阵‌: Mat zeros Mat::zeros(3, 3, CV_32F); // 3x3浮点零矩阵 Mat eye Mat::eye(3, 3, CV_32F); // 3x3单位矩阵 自定义初始化‌&#xff1a…

【C++进阶】函数:深度解析 C++ 函数的 12 大进化特性

目录 一、函数基础 1.1 函数定义与声明 1.2 函数调用 1.3 引用参数 二、函数重载:同名函数的「多态魔法」(C 特有) 2.1 基础实现 2.2 重载决议流程图 2.3 与 C 语言的本质区别 2.4 实战陷阱 三、默认参数:接口的「弹性设…

spring boot 登入权限RBAC模式

首先准备好5张表 user_info表,用户的信息表 role表,角色表(比如超级管理员、管理员、审核员、采购......) 创建user_role表,user_info表,role表的中间表 注意了,role_id和user_id是 u…

C#里使用libxl来对列或行进行分组显示

有时候由于EXCEL里的行数很多, 需要把某些行进行隐藏起来,那么就需要使用到行或列进行隐藏的操作。 这时候需要使用函数GroupCols和GroupRows来对这些列或行进行分组。 分组不能出现交叉的情况,否则会抛出异常。 如下图所示: 可以使用下面的代码来输出上面的EXCEL: p…

LangChain 基础

一、LangChain 模块和体系 LangChain 是一个用于开发由大型语言模型(LLMs)驱动的应用程序的框架。 官方文档:https://python.langchain.com/docs/introduction/ LangChain 简化了LLM应用程序生命周期的每个阶段: 开发&#xf…

IDEA 快捷键ctrl+shift+f 无法全局搜索内容的问题及解决办法

本篇文章主要讲解IDEA、phpStrom、webStrom、pyCharm等jetbrains系列编辑器无法进行全局搜索内容问题的主要原因及解决办法。 日期:2025年3月22日 作者:任聪聪 现象描述: 1.按下ctrlshiftf 输入法转为了繁体。 2.快捷键ctrlshiftr 可以全局检…

2025年- G24-Lc98-217.包含重复(使用hashSet解决)-java版

1.题目描述 2.思路 思路一: 我的想法是直接用集合来判断,如果集合的元素不能添加说明之前已经存在这个元素,也就是发现了重复元素,所以返回false。 补充一: Map、ArrayList的定义和声明 3.代码实现 class Soluti…

MySQL事务全解析:从概念到实战

在数据库操作中,事务是一个至关重要的概念,它确保了数据的完整性和一致性。今天,就让我们深入探讨MySQL事务的方方面面,从基础概念到实际应用,全面掌握这一技能。 一、为什么需要事务 假设张三要给李四转账100元&…

CVPR 2025 | 文本和图像引导的高保真3D数字人高效生成GaussianIP

小小宣传一下CVPR 2025的工作GaussianIP。 arXiv:https://arxiv.org/abs/2503.11143 Github:https://github.com/silence-tang/GaussianIP 欢迎star, issue~ 摘要 文本引导的3D人体生成随着高效3D表示及2D升维方法(如SDS)的发展…