RMI 总结之 Socket 二

基于RMI和Socket的Java聊天软件 Java期末大作业,总算肝完了。这学期才开始接触Java,比起C语言java用起来不要太舒服。期末大作业就想着做一个能用的东西出来,于是就选了这个,经过小组成员的努力,最终还是把这玩意儿弄出来了。 服务器端: 采用RMI和Socket实现服务器端与客户端通信 关于RMI 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录服务器端:前言一、功能介绍及环境二、服务器端1.RMI2.Socket3.数据库4.基本逻辑三、客户端四、部署到服务器总结 前言 java大作业总算肝完了。这一路 阅读详情

在前一章节中,我们讲到RMI框架的底层就是ServerSocket和Socket之间的通信。如果到此就停止脚步,难免会让人惋惜。为了不留遗憾,我决定继续停留此处,慢慢欣赏这多彩的世界。

在上节我们看到连接RMI服务端的客户端程序,最终调用了TCPDirectSocketFactory类的createSocket()方法。该类的具体代码如下所示:

public class TCPDirectSocketFactory extends RMISocketFactory {

    public Socket createSocket(String host, int port) throws IOException
    {
        return new Socket(host, port);
    }

    public ServerSocket createServerSocket(int port) throws IOException
    {
        return new ServerSocket(port);
    }
}

看到new Socket(host, port);,不知道你是什么状态,反正我飘了,想立马跑出出租屋,在大街上发疯。但在理智的监督下,我没得做出如此出格的事情。于是继续向下看,下述代码来源于TCPEndpoint# newSocket():

try {
    socket.setTcpNoDelay(true);
} catch (Exception e) {
    // if we fail to set this, ignore and proceed anyway
}

// fix 4187495: explicitly set SO_KEEPALIVE to prevent client hangs
try {
    socket.setKeepAlive(true);
} catch (Exception e) {
    // ignore and proceed
}

这是什么?它们有啥作用?老天,我居然不知道,等等后面好像还有类似的东西,以下代码来自TCPChannel#createConnection():

int originalSoTimeout = 0;
try {
    originalSoTimeout = sock.getSoTimeout();
    sock.setSoTimeout(handshakeTimeout);
} catch (Exception e) {
    // if we fail to set this, ignore and proceed anyway
}
// 中间删除了一些代码,详情请见源码
try {
    /*
     * If socket factory had set a non-zero timeout on its
     * own, then restore it instead of using the property-
     * configured value.
     */
    sock.setSoTimeout((originalSoTimeout != 0 ?
                       originalSoTimeout :
                       responseTimeout));
} catch (Exception e) {
    // if we fail to set this, ignore and proceed anyway
}

好了好了,先到这里吧,已经无法继续了,后面的代码已经把我绕晕了。不过还是先总结一下:

  • Socket对象的创建。创建Socket的方式有很多,常用的构造方法有以下几个:
  1. Socket()
  2. Socket(InetAddress address, int port) throws UnknownHostException,IOException
  3. Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException
  4. Socket(String host, int port) throws UnknownHostException,IOException
  5. Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException
  6. Socket(Proxy proxy)

这些方法中,除了第一个无参构造方法外,其他构造方法都会试图与服务器之间建立一个连接,一旦连接成功,就会返回一个 Socket 对象,否则抛出异常。不过这里有一点需要我们注意一下,这些尝试与服务器之间建立连接的构造方法,默认情况下,会一直等待下去,直到连接成功,或者出现异常。但我们要清楚,如果底层网络不稳定,通过构造方法创建连接的动作会一直等待下去,我想这不是大家想看到的吧!那有没有办法让他不要一直等待下去呢?方法肯定是有的。就是第一个无参构造方法和connect()方法结合。具体代码如下所示:

Socket socket = new Socket();

socket.connect(new InetSocketAddress("127.0.0.1", 1099), 60000);

上述代码表示创建一个客户端到服务器之间的连接,如果在一分钟之内出现某种异常,则抛出该异常,如果在一分钟后既没有连接成功,也没有出现异常,那么就抛出 SocketTimeout-Exception异常。如果在一分钟内连接成功,则 connect() 方法正常返回。由此我们可以知道上述代码表示在创建连接时会等待一分钟,从而避免一直等待下去。注意:这里的60000单位是毫秒。

  • Socket中相关信息的获取。在一个 Socket 对象中同时包含了远程服务器的 IP 地址和端口信息,以及客户本地的 IP 地址和端口信息。此外,从 Socket 对象中还可以获得输出流和输入流,分别用于向服务器发送数据,以及接收从服务器端发来的数据。
  1. getInetAddress()  // 获得远程被连接进程的IP地址
  2. getPort()  // 获得远程被连接进程的端口
  3. getLocalAddress()  // 获得本地的IP地址
  4. getLocalPort()  // 获得本地的端口
  5. getInputStream()  // 获得输入流,如果Socket还没有连接,或者已经关团,或者已经通过shutdownInput()方法关闭输入流,那么此方法会抛出IOException
  6. getOutputStream()  // 获得输出流,如果Socket还没有连接,或者已经关闭,或者已经通过shutdownOutput()方法关闭输出流,那么此方法会抛出 IOException
  • Socket相关设置选项
  1. TCP_NODELAY:表示立即发送数据。在默认情况下发送数据采用 Negale 算法,发送方发送的数据不会立刻被发出,而是先放在缓冲区内,等缓冲区满了再发出。发送完一批数据后,会等待接收方对这批数据的回应,然后发送下一批数据。此算法法适用于发送方需要发送大批量数据并且接收方会及时做出回应的场合,这种算法通过减少传输数据的次数来提高通信效率。如果发送方持续地发送小批量的数据。并且接收方不一定会立即发送响应数据,那么 Negale 算法会使发送方运行得很慢,对于GU程序,比如网络游戏程序(服务器需要实时跟踪客户端鼠标的移动),这个问题尤其突出。TCP_NODEALY 的默认值为 false,表示采用 Negale 算法,如果调用 setTcpNoDelay(true) 方法,就会关闭 Socket 的缓冲,确保数据被及时发送:if(!socket.getTcpNoDelay()) { socket.setTcpNoDelay(true); }
  2. SO_RESUSEADDR:表示是否允许重用 Socket 所绑定的本地地址。当接收方通过 Socket 的 close() 方法关闭 Socket 时,如果网络上还有发送到这个 Socket 的数据,那么底层的 Socket 不会立刻释放本地端口,而是会等待一段时间,确保接收到了网络上发送过来的延迟数据,再释放端口。Socket 接收到延迟数据后,不会对这些数据做任何处理。Socket 接收延迟数据的目的是,确保这些数据不会被其他碰巧绑定到同样端口的新进程接收到。客户程序一般采用随机端口,因此出现两个客户程序绑定到同样端口的可能性不大。许多服务器程序都使用固定的端口。当服务器程序被关闭后,有可能它的端口还会被占用一段时间,如果此时立刻在同一台主机上重启服务器程序,由于端口已经被占用,使得服务感程序无法绑定到该端口,导致启动失败。为了确保当一个进程关闭了 Socket 后,即便它还没释放端口,同一台主机上的其他进要也可以立刻重用该端口,可以调用 Socke 的 setResuseAddress(ture) 方法:if(!socket.getResuseAddress()) { socket.setResuseAddress(true); }。值得注意的是 socket.setResuseAddress(true) 方法必须在 Socket 还没有被绑定到一个本地端口之前调用,否则执行无效
  3. SO_TIMEOUT:表示接收数据时的等待超时时间。当通过 Socket 的输入流读数据时,如果还没有数据,就会等待。Socket 类的SO_TIMEOUT 选项用于设定接收数据的等待超时时间,单位为 ms,它的默认值为0,表示会无限等待,永远不会超时。以下代码把接收数据的等待超时时间设为三分钟:if(socket.getTimeout() == 0) { socket.setTimeout(60000 * 3); };Socket 的 setTimeout() 方法必须在接收数据之前执行才有效
  4. SO_LINGER:表示与执行 Socket 的 close() 方法时,是否立即关闭底层的 Socket。在默认情况下执行 Socket 的 close() 方法,该方法会立即返回,但底层的 Socket 实际上并不立即关闭,它会延迟一段时间,直到发送完所有剩余的数据,才会真正关闭 Socket。如果执行以下方法:socket.setSoLinger(true,0);。那么执行 Socket 的 close() 方法,该方法也会立即返回而且底层的 Socket 也会立即关闭,所有未发送完的数据被丢弃。如果执行以下方法:socke-t.setSoLinger(true,3600);。那么执行 Socket 的 close() 方法,该方法不会立即返回,而是进入阻塞状态,同时,底层的 Socket 会尝试发送剩余的数据。只有满足以下两个条件之一,close() 方法才返回:1)底层的 Socket 已经发送完所有的剩余数据;2)尽管底层的 Socket 还没有发送完所有的剩余数据,但己经阻塞了 3600s,此时 close() 也会返回,未发送的数据被丢弃
  5. SO_RCVBUF:表示接收数据的缓冲区的大小。一般说来,传输大的连续的数据块,比如基于 HTTP 或 FTP 的通信,可以使用较大的缓冲区,这可以减少传输数据的次数,提高传输数据的效率。而对于交互式的通信方式,比如 Telnet 和网络游戏,则应该采用小的缓冲区,确保小批量的数据能及时发送给对方
  6. SO_SNDBUF:表示发送数据的缓冲区的大小
  7. SO_KEEPALIVE:表示对于长时间处于空闲状态的 Socket,是否要自动把它关闭。当 SO_KEEPALIVE 选项为 tue 时,表示底层的 TCP 实现会监视该连接是否有效连接,是否处于空闲状态,即连接的两端没有互相传送数据超过了 2 小时,本地的 TCP 实现发送一个数据包给远程的 Socket,如果远程 Socke 没有返回响应,TCP 实现就会持续尝试发送 11 分钟,直到接收到响应为止。如果在 12 分钟内未收到响应,TCP 实现就会自动关闭本地 Socket,断开连接。SO_KEEPALIVE 选项的默认值为 false,表示 TCP 不会监视连接是否有效,不活动的客户端可能会永久存在下去,而不会注意到服务器已经崩溃

Java远程方法调用(RMI)技术详解 Java RMI(远程方法调用)采用三层架构实现分布式通信,包含注册表服务、服务端和客户端三大核心组件。服务端通过导出远程对象并绑定到注册表,客户端通过接口契约查找并调用远程方法。RMI采用租约机制管理远程对象生命周期,通过引用计数和定期续租实现分布式垃圾回收。开发时需要严格分离服务端与客户端代码,通过模块化部署确保安全性,并注意注册表必须与服务器同机部署。RMI架构隐藏了底层网络通信细节,使远程调用语法与本地调用保持一致,同时处理了对象定位、参数序列化和异常处理等分布式环境下的复杂问题。 阅读详情

相关推荐

企业级智能问数开发的核心痛点与技术聚焦

本文介绍了企业级智能问数系统开发的三大核心问题和解决方案:语义解析不精准、SQL生成不健壮、企业适配难落地。文章从开发者视角出发,详细拆解了NLU语义解析、SQL生成、对话记忆、企业级适配四大核心模块的技术实现。 在技术选型方面,推荐了LangChain+DeepSeek-R1、FAISS/Milvus、SQLAlchemy等工具链组合。针对企业级需求,重点讲解了: 语义解析模块的意图识别优化和要素提取技术 SQL生成模块的语法校验与性能优化方案 对话记忆模块的Redis存储实现 企业级适配的三层防护体系和

lamehsl的专栏 1047

Java Socket 参数详解 setKeepAlive

Java socket 编程中有个 keepalive 选项,看到这个选项经常会误解为长连接,不设置则为短连接,实则不然。 socket 连接建立之后,只要双方均未主动关闭连接,那这个连接就是会一直保持的,就是持久的连接 keepalive 只是为了防止连接的双方发生意外而通知不到对方,导致一方还持有连接,占用资源 其实这个选项的意思是TCP连接空闲时是否需要向对方发送探测包,实际上是依赖于底层的...

南淮北安的博客 8746

rk3588s-摄像头适配gc8034

若还打开失败,需要看下XML中文件配置是否与DTS配置信息一致,或者XML参数配置是否有异常;MIPI摄像头是有上电时序要求,具体时序要查看sensor芯片对应的datasheet进行修改,如果时序不满足,sensor无法正常,此时用i2ctool去查看设备可能无法扫面到设备,即是i2c设备找不到。RK3588或者RK3588S有路MIPI-PHY,驱动开发工程师需要根据对应的硬件原图进行配置,以下会讲解分别使用MIPI-DPHY和MIPI-D/CPHY如何在DTS配置mipi摄像头的回环链路。

Yxx8066的博客 2200

Socket 关于设置Socket连接超时时间

做网络编程的人对setSoTimeout方法一定很熟悉,都知道是设置连接的超时时间! 但是我在网上找资料时发现很多人把这个超时时间理解成了链路的超时时间!我看了一下JDK 关于这个方法的说明,其实根本不是链路的超时时间!   setSoTimeout public void setSoTimeout(int timeout) throws SocketException启用/禁用带有...

java小强 4532

【TensorRT】TensorRT C# API 项目介绍:基于C#与TensorRT部署深度学习模型(上篇)

开发了TensorRT C# API 2.0版本,该版本在开发时充分考虑了上一版本应用时出现的问题,并进行了改进。同时在本版本中,我们对接口进行了优化,使用起来更加简单,并同时提供了相关的应用案例,方便开发者进行使用。

grape_yan的博客 3038

ArcGIS基础:CAD数据转换为GIS数据(符号化显示、数据转换、线转面、空间连接)

1、符号化显示: CAD数据加载进来有很多列表,包含了点【point】、线【polyline】、面【polygon】、标注数据【Annotation】等数据,本次实验我们需要用到的是面数据,也就是.dwgPolygong格式的数据。如下图所示: 把数据加载进来,然后在2处打开属性表,查看CAD数据的属性表,打开后可以发现【layer】图层表示就是地块的用地性质,它就是符号化显示的依据。 我们在数据上右键【属性】,打开图层属性,找到【符号系统】,选择类别中的【唯一值】,然后在【值字段】下拉选择【layer】,

yuanYW7556的博客 2万+

Socket心跳包机制总结

跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。     在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而

全冉 的博客 5万+

HDLbits找茬实战:5个Verilog仿真Bug修复案例,新手避坑指南

本文通过HDLbits平台上的5个典型Verilog仿真Bug案例,详细解析了多路选择器位宽不匹配、模块实例化端口映射错误等常见问题,提供实用的修复方案和调试技巧,帮助Verilog新手快速掌握代码验证与仿真技能,避免常见陷阱。

weixin_42653691的博客 162

Socket网络编程keepalive(探测包)

Socket网络编程的心跳(探测包) 什么是keepAlive 设置keepAlive有什么用 如何设置keepAlive 1).什么是keepALive: keepalive是soket中的心跳包,用来判断当前socket是否是联通的状态,keepalive默认是关闭的,因为虽然流量很小,但毕竟也是网络开销,因此需要用户手动开启 2).设置keepalive有什么用: 优点 判断当前socket是否处于连接状态,socket设置有两种模式,一般只有在把socket设置为非阻塞模式才会去设置心跳包,因为

weixin_43269452的博客 4447

DeepSeek 赋能智慧消防:以 AI 之力筑牢城市安全 “防火墙”

在数字化浪潮下,智慧消防系统亟需先进技术提升效能。DeepSeek 凭借 Transformer 架构与混合专家架构等核心技术,具备强大的多模态数据处理与智能决策能力,且支持本地化部署,保障数据安全。其在智慧消防领域的应用成效显著,从实现火灾风险动态感知与早期精准预警,到优化智能接警调度、设备健康管理,再到辅助应急指挥与疏散,有效降低火灾风险与事故损失。未来,DeepSeek 有望在智慧消防领域持续拓展,同时也需应对技术、数据等多方面挑战。

邓邓子的博客 1690

YOLOv11改进,YOLOv11引入B2CNet的BFAM(双时相特征聚合模块),JSTARS 2024,二次创新C3k2结构

YOLOv11改进,YOLOv11引入B2CNet的BFAM(双时相特征聚合模块),JSTARS 2024,二次创新C3k2结构

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 406

Java网络编程Socket

Java网络编程Socket

u014644574的博客 6897

一文吃透 ABAP CDS SELECT:语法全景、关联与去重、可运行示例与实战心法

摘要: 本文深入解析ABAP中CDS视图的SELECT语法,重点介绍两种等价写法、关联与路径表达式优化、DISTINCT去重逻辑及WHERE/GROUP BY/HAVING/UNION等子句的应用。通过可运行的业务伙伴角色去重、关联路径查询及多角色筛选示例,演示如何将CDS特性转化为项目实践。强调关联复用性优于传统JOIN,并指出DISTINCT的权限边界与误用场景,帮助开发者从行式思维转向图式数据建模。(150字) 关键词: ABAP CDS、SELECT语法、路径表达式、DISTINCT去重、关联复用

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 391

http、RMI、socket、rpc、hessian比较

http、RMI、socket、rpc、hessian比较 原文:http://blog.youkuaiyun.com/zc529739024/article/details/55519733 作者:优快云 – 17奋斗8 SOCKET使用时可以指定协议TCP,UDP等; RIM:使用JRMP协议,JRMP又是基于TCP/IP; RPC:底层使用SOCKET接口,定义了

huangshulang1234的博客 2041

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

RMI 总结之 Socket 一

单JVM进程中,对象之间的交流非常简答:A类中new一个B类对象,然后通过这个对象直接调用B类中定义的方法;反过来B类想要调用A类中的方法,同样可以在B类中new一个A类对象,然后用这个对象直接调用A类中定义的方法即可。但这个方法无法使分布在不同JVM进程中的两个对象进行交流。那它们之间就无法交流了吗?相信聪明的你已经找到了使活跃在不同JVM进程中的两个对象进行交流的可靠方法。

java_lover20111106的博客 1931

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

rmi webservice socket 协议 区别

应用层的通讯协议: http https pops smtp ftp * 传输层协议: tcp udp * 网络层协议: ip  Socket是使用在传输层的一种技术。     java jdk中分别实现了基于tcp的socket -- java.net.Socket  java.net.ServerSocket                                 基于udp

痕迹 1595

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

RMI和socket详解

详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp58   一般来说,基于CS(client-server)软件架构的开发技术有很多种。比较常用的有:基于socket的网络编程、RPC、基于Java技术的RMI(当然C#也有类似技术)、CORBA等。在这里我们只是对基于socket的网络编程与RMI作个对比,有助于我们

yemou_blog的博客 1263

RMI 与 Socket 的比较与浅析

一般来说,基于 CS(client-server) 软件架构的开发技术有很多种。比较常用的有:基于socket的网络编程、RPC、基于Java技术的RMI(当然C#也有类似技术)、CORBA等。在这里我们只是对基于socket的网络编程与RMI作个对比,有助于我们了解它们各自的应用领域,帮助我们在面对一个具体问题的时候选用适合的技术。另外,本文所做的讨论可以认为是脱离了语言层面的东西,只是对技术的

稚枭天卓 970

RMI和socket简介

一般来说,基于CS(client-server)软件架构的开发技术有很多种。比较常用的有:基于socket的网络编程、RPC、基于Java技术的RMI(当然C#也有类似技术)、CORBA等。在这里我们只是对基于socket的网络编程与RMI作个对比,有助于我们了解它们各自的应用领域,帮助我们在面对一个具体问题的时候选用适合的技术。另外,本文所做的讨论可以认为是脱离了语言层面的东西,只是对技术的本身做一个讨论,无关乎你是用C++、C#或Java 在开发。 一、RMI技术简介 本文就以Java为.

weixin_57763462的博客 433

JAVA socket FTPserver HTTPserver chatting RMI(Remote Method Invocation) | socket实现ftp http rmi chat

github-httpserverftpserverchattingRoomRMI RMI Remote Method Invocation httpserver遇到的问题 FTP 客户端连接到服务器端 c伪码 客户端连接到 FTP 服务器接收欢迎信息 客户端发送用户名和密码登入 FTP 服务器 让服务器进入被动模式在数据端口监听 客户端通过被动模式下载文件 遇到的问题 Chatting功能 服务器

安 2284

Socket与RMI比较

当你的应用不需要在client与server之间传输大量的数据时,RMI是较好的选择,它简洁、易于开发。

它山之石,可以攻玉 8560

Java RMI VS TCP Socket

RMI比较socket的网络编程主要有以下几个方面: 第一、.RMI是面向对象的,而后者不是。 第二、.RMI是与语言相绑定的。比如当你使用Java RMI技术的时候,客户端与服务器端都必须使用Java开发。而socket的网络编程是使用独立于开发语言的,甚至独立于平台。基于socket的网络编程,客户端与服务器端可以使用不同开发语言和不同的平台。 第三、从网络协议栈...

weixin_30795127的博客 203

java socket rmi_Java RMI VS TCP Socket

RMI比较socket的网络编程主要有以下几个方面:第一、.RMI是面向对象的,而后者不是。第二、.RMI是与语言相绑定的。比如当你使用Java RMI技术的时候,客户端与服务器端都必须使用Java开发。而socket的网络编程是使用独立于开发语言的,甚至独立于平台。基于socket的网络编程,客户端与服务器端可以使用不同开发语言和不同的平台。第三、从网络协议栈的观点来看,RMI与socket的网...

weixin_42504214的博客 148

java socket rmi_RMI和socket详解

一般来说,基于CS(client-server)软件架构的开发技术有很多种。比较常用的有:基于socket的网络编程、RPC、基于Java技术的RMI(当然C#也有类似技术)、CORBA等。在这里我们只是对基于socket的网络编程与RMI作个对比,有助于我们了解它们各自的应用领域,帮助我们在面对一个具体问题的时候选用适合的技术。另外,本文所做的讨论可以认为是脱离了语言层面的东西,只是对技术的本身...

weixin_35594924的博客 290

RMI和Socket的比较及区别(转)

一般来说,基于CS(client-server)软件架构的开发技术有很多种。比较常用的有:基于socket的网络编程、RPC、基于Java技术的 RMI(当然C#也有类似技术)、CORBA等。在这里我们只是对基于socket的网络编程与RMI作个对比,有助于我们了解它们各自的应用领域,帮助我们在面对一个具体问题的时候选用适合的技术。另外,本文所做的讨论可以认为是脱离了语言层面的东西,只是对技术的本

二次加工是一种痛 833
上一篇: RMI 总结之 Socket 一
下一篇: Spring AOP 总结一
机器挖掘工
博客等级 码龄11年 892粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器挖掘工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值