认识netty+实战

Netty实战(一)Nett的概念及体系结构 Netty是由JBOSS提供的一个java开源框架,它提供异步的、事件驱动的网络应用程序框架和工具。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。 阅读详情

认识netty+实战

官网:https://netty.io/

一、初识netty

1、Netty 由JBOSS提供的一个开源框架,现为github上的独立项目
2、Netty是一个异步的、基于事件驱动的网络应用框架,用于快速开发高性能、高可靠性的网络IO程序
在这里插入图片描述
3、Netty主要是针对TCP/IP协议下,面向客户端的高并发应用,或者peer-to-peer场景下的大量数据的持续传输的应用。
在这里插入图片描述
4、Netty本质是NIO框架,适用于服务器通讯相关的多种应用场景

二、Netty应用场景

1、互联网行业

1)互联网行业∶在分布式系统中,主节点之间需要远程服务调用,高性能的RPC框架比不可少的一部分,Netty作为异步高性能的通信框架,往往作为基础通信组件这些RPC框架所使用。
2)典型应用:阿里的分布式服务框架Dubbo的RPC框架使用Dubbo协议进行节点通信,Dubbo协议默认使用Netty作为基础通信组件,用于实现各个进程节点之间的内部通信。

2、游戏行业

1)无论手游服务端还是大型的网络游戏
2)Netty 作为高性能的基础通信组件,提供了TCP/UDP和HTTP协议栈,方便定制和开发私有协议栈
3)地图服务器之间可以方便的通过Netty进行高性能通信

3、大数据领域

1)经典的Hadoop的高性能通信和序列化组件(AVRO实现数据文件共享)的RPC框架,默认采用Netty进行跨节点的通信。
2)Netty Service基于Netty框架第二次封装实现。

4、其他开源项目使用到netty

https://netty.io/wiki/related-projects.html

三、书籍推荐

1、Netty Inaction:实战性比较强
2、Netty权威指南:理论原理性较强

四、Netty名词介绍

1、阻塞和非阻塞

1)线程访问资源,该资源是否准备就绪的一种处理方式

在这里插入图片描述
2、BIO

同步阻塞IO,Block lO

在这里插入图片描述
3、NIO

同步非阻塞IO,New lO (Non-block lO)

在这里插入图片描述
4、AIO

异步非阻塞的IO(比较懒,等待别人通知)

Netty线程模型(Reactor线程模型)

一、单线程模型

所有的IO操作都由同一个NIO线程处理的

在这里插入图片描述
适用于小型应用场景。。。

二、多线程模型

由一组NIO线程处理IO操作

在这里插入图片描述
单线程就像是饭店门口的接待员,后面的线程池就像是饭店里面的服务员。。。

三、主从线程模型

在这里插入图片描述

Netty服务器搭建

1)构建一对主从线程池
2)定义服务器启动类
3)为服务器设置channel
4)设置处理从线程池的助手类初始化起
5)监听启动和关闭服务器

首先,创建maven项目,导入netty依赖

<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
	<groupId>io.netty</groupId>
	<artifactId>netty-all</artifactId>
	<version>4.1.49.Final</version>
</dependency>

创建服务器类:实现客户端发送请求,服务器给予响应:

 public class HelloNettyServer {
	public static void main(String[ ] args) throws Exception {
		//创建一组线程池组
		//主线程池:用于接受客户端的请求链接,不做任何处理
		EventLoopGroup group1 = new NioEventLoopGroup();
		//从线程池:主线程池会把任务交给它,让其做任务
		EventLoopGroup group2 = new NioEventLoopGroup();
		try {
			//创建服务器启动类
			serverBootstrap serverBootstrap = new ServerBootstrap();
			serverBootstrap.group(group1,group2)//设置主从线程组
							.channel(NioServerSocketChannel.class)//设置nio双向通道
							.childHandler(null);//添加子处理器,用于处理从线程池的任务
			//启动服务,并且设置端口号,同时启动方式为同步
			ChannelFuture channelFuture = serverBootstrap.bind(8888).sync();//监听关闭的channel,设置为同步方式
			channelFuture.channel().closeFuture().sync();
		}finally{
			group1.shutdownGracefully();
			group2.shutdownGracefully();
		}
}

设置channel初始化器:
每一个channel由多个handler共同组成的管道(pipeline) ;
在这里插入图片描述
初始化器,channel注册之后,会执行里边的响应的初始化方法:

public class HelloNettyServerInitializer extends ChannelInitializer<SocketChannel> {
	@Override
	protected void initChannel(SocketChannel channel) throws Exception {
		//通过SocketChannel去获得对应的管道
		ChannelPipeline pipeline = channel.pipeline();
		/**
		 * 通过管道添加handler
		 * HttpServerCodec:是由netty自己提供的助手类,可以理解为拦截器
		 * 当请求到服务器,我们需要解码,响应到客户端做编码
		*/
		pipeline.addLast("HttpServerCodec",new HttpServerCodec());
		//添加自定义助手类,给客户端浏览器渲染hello netty~
		pipeline.addLast("CustomHandler",new CustomHandler());
	}
}
serverBootstrap.group(group1,group2)//设置主从线程组
							.channel(NioServerSocketChannel.class)//设置nio双向通道
							.childHandler(HelloNettyServerInitializer);//添加子处理器,用于处理从线程池的任务

自定义助手类:

public class CustomHandler extends SimpleChannelInboundHandler<Http0bject> {
	@Override
	protected void channelRead0(ChannelHandlerContext ctx,HttpObject msg) throws Exception {
		//获取channel
		Channel channel = ctx.channel();
		if(msg instanceof HttpRequest){ //判断一下是否是HTTP请求
			//在控制台打印远程地址
			System.out.println(channel.remoteAddress());
			//定义向客户端发送的数据内容
			ByteBuf content = Unpooled.copiedBuffer("hello netty~",CharsetUtil.UTF_8);
			//构建http response
			FullHttpResponse response= new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK,content);
			//为响应增加数据类型和长度
			response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
			response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());
			//把响应渲染到html客户端页面上
			ctx.writeAndFlush(response);
		}
	}

	//生命周期======================================================================================
	@Override
	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
		System.out.println("channel注册");
	}
	@Override
	public void channelUnregistered(ChannelHandlerContext ctx) throws Exception
		System.out.println( "channel移除");
	}
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		System.out.println("channel活跃");
	}
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		System.out. println( "channel不活跃");
	}
	@Override
	public void userEventTriggered(ChannelHandlerContext ctx,0bject evt) throws Exception {
		System.out.println("用户事件触发");
	}
	@Override
	public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
		System.out.println("channel可写更改");
	}
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception {
		System.out.println("捕获到异常");
	}
	@Override
	public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
		System.out.println("助手类添加");
	}
	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		System.out.println("助手类移除");
	}
}

测试:启动服务端。开启浏览器查看:
在这里插入图片描述
在这里插入图片描述

Netty实时通信原理

一、实时通信

1、Ajax轮询
2、long pull
3、websocket (目前主要)
- 3.1 持久化的协议
- 3.2 主动实时反馈服务端信息

写一个WebSocketServer:

public class webSocketServer{
public static void main(String[] args) throws Exception {
	//创建主从线程池
	EventLoopGroup mainGroup = new NioEventLoopGroup();
	EventLoopGroup subGroup = new NioEventLoopGroup(;
	try {
		//创建服务器类
		ServerBootstrap server = new ServerBootstrap();
		server.group(mainGroup,subGroup)
			  .channel(NioserverSocketChannel.class)
			  .childHandler(new WSServerInitialzer());
		ChannelFuture future = server.bind(8088).sync();
		future.channel().closeFuture().sync();
	}finally {
		mainGroup.shutdownGracefully();
		subGroup.shutdownGracefully();
	}
}
public class WSServerInitialzer extends ChannelInitializer<SocketChannel> {
	@Override
	protected void initChannel(SocketChannel channel) throws Exception {
		//获取管道(pipeline)
		ChannelPipeline pipeline = channel.pipeline() ;
		// websocket基于http协议,所需要的http编解码器
		pipeline.addLast(new HttpServerCodec());
		//在http上有一些数据流产生,有大有小,我们对其进行处理,既然如此,我们需要使用netty对下数据流写提供支持,这个类叫ChunkedWriteHandler
		pipeline.addLast(new ChunkedWriteHandler());
		//对httpMessage进行聚合处理,聚合成request或response
		pipeline.addLast(new HttpObjectAggregator(1024*64));
	/**
	*本handler会帮你处理一些繁重复杂的事情
	*会帮你处理握手动作: handshaking (close、ping、pong) ping+pong =心跳
	*对于websocket来讲,都是以frams进行传输的,不同的数据类型对应的fnams也不同
	*/
		pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));

		//自定义的handler
		pipeline.addLast(new ChatHandler());
	}
}

用于处理消息的handler:
由于它的传输数据的载体是frame,这个frame 在netty中,是用于为websocket专门处理文本对象的,frame是消息的载体,此类叫:TextWebsocketFrame

public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>{
	//用于记录和管理所有客户端的channel
	private static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
	
	@Override
	protected void channelRead0(ChannelHandlerContext ctx,TextWebSocketFrame msg) throws Exception {
		//获取客户端所传输的消息
		String content = msg.text();
		System.out.println("接收到的数据:"+content);
		//将数据刷新到客户端上
		clients.writeAndFlush(
			new TextWebSocketFrame(
				"[服务器在:]"+ LocalDateTime.now()
				+"接收到消息,消息内容为: "+content));
	}
	@Override
	public void hanglerAdded(ChannelHandlerContext ctx) throws Exception {
		clients.add(ctx.channel());
	}
	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		//clients.remove(ctx.channel());
		System.out.println("客户端断开,channel对应的长Id为:"+ctx.channel().id().asLongText());
		System.out.println("客户端断开,channel对应的短Id为:"+ctx.channel().id().asShortText());
	}
}

二、websocket api(JS)

1) var socket = new WebSocket("ws://ip:[port]");
2) 生命周期: onopen()(只触发一次),onmessage()只要二者建立连接,服务端向客户端推送消息,就会触发此函数,onerror(),onclose()。
3) 主动方法:Socket.send(), Socket.close();

<!DOCTYPE html><html>
	<head>
		<meta charset="utf-8">
		<title>Netty实时通信</title>
	</head>
	<body>
		发送消息:<input type="text" id="msgcontent"/>
		<input type="button" value="发送消息" onclick=“CHAT.chat()”/>
		<hr />
		接收消息:
		<div id="receiveMsg"></div>
		
		<script type="text/javascript">
			window.CHAT = {
				socket: null,
				init:function(){
					//判断浏览器是否支持websocket
					if(window.webSocket){
						//创建websocket对象
						CHAT.socket = new webSocket("ws://192.168.0.101:8088/ws");
						CHAT.socket.onopen = function(){
							console.log("链接建立成功");
						},
						CHAT.socket.close=function(){		
							console.log("链接关闭");
						},
						CHAT.socket.onerror = function(){
							console.log("发生异常"");
						},
						CHAT.socket.onmessage = function(e){
							console.log("接受消息:"+e.data);
							var receiveMsg = document.getElementById("receiveMsg");
							var html= receiveMsg.innerHTML;//获取本对象原有的内容
							//嵌入新的内容
							receiveMsg.innerHTML= html + "<br/>" + e.data;
						},
					}else{
						console.log("您的浏览器不支持websocket协议");
					},
				chat:function(){
					//获取发送消息框中所输入内容
					var msgContent = document.getElementById("msgContent").value;
					//将客户输入的消息进行发送
					CHAT.socket.send(msgContent);
				};
			CHAT.init( );
		</script>
	</body>
</html>

启动后台WebSocket服务:
在这里插入图片描述
在这里插入图片描述
【参考】https://www.bilibili.com/video/BV1Zf4y137sY?p=23

【网络编程(三)】Netty入门到实战这一篇就够了 向ServerBootstrap传递俩个EventLoopGroup,第一个称为BoosGroup用来处理新用户的连接请求,而第二个称为WorkerGroup,用来处理读写操作和业务逻辑,也是为什么一般给BoosGroup线程数设置为1就够用的原因,因为它只处理连接请求 阅读详情

相关推荐

「深入浅出Netty」不愧是阿里架构师,这篇Netty实战文档太实用

前言 什么是Netty? Netty是由JBOSS提供的一个java开源框架。 Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。也就是说,Netty是一个基于NIO的客户,服务器端编程框架,使用Netty可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。 作为当前最流行的NIO框架,Netty在互联...

zhuguanghalo的博客 2358

Netty实战

Netty提供了两种实现,PooledByteBufAllocator(默认)和 UnpooledByteBufAllocator,前者池化了ByteBuf的实例,以提高系统性能最大限度的减少内存碎片,后者的实现不池化ByteBuf实例,每次调用都返回一个新的实例。优点:将客户端的Socket包装成一个Task(该任务实现了Runnable接口)投递到后端的线程池中进行处理,由于线程池可以设置消息队列的大小和最大线程数,因此资源占用是可控的,无论多少个客户端并发访问,都不会导致资源的耗尽和宕机。

aoligeiaoligei的博客 1327

《Netty+JavaFx实战:仿桌面版微信聊天》代码开源、上云部署、视频讲解,只为让你给点个Star!

作者:小傅哥 博客:https://bugstack.cn 视频:https://mp.weixin.qq.com/s/OmXCY4fTfDpkvjlg5ME0ZA 源码:https://github.com/fuzhengwei/NaiveChat 本项目是作者小傅哥使用JavaFx、Netty4.x、SpringBoot、Mysql等技术栈和偏向于DDD领域驱动设计方式,搭建的仿桌面版微信...

bugstack虫洞栈 5480

Netty 实战

请思考,因为 pipeline 的存在,一般需要将 ByteBuf 传递给下一个 ChannelHandler,如果在 finally 中 release 了,就失去了传递性(当然,如果在这个 ChannelHandler 内这个 ByteBuf 已完成了它的使命,那么便无须再传递)负载,但是却造成了延时,而该参数的作用就是禁止使用Nagle算法,使用于小数据即时传输,于TCP_NODELAY相对应的是TCP_CORK,该选项是需要等到发送的数据量最大的时候,一次性发送数据,适用于文件传输。

prcyang的专栏 1225

Netty网络编程实战4,使用Netty实现心跳检测机制

Java高并发编程实战系列,打造精品专栏。

学Java,找哪吒 5585

python制作图形化小游戏_创意编程|Python的GUI简易界面设计测测你的反应力

Python的GUI简易界面设计案例测测你的反应力作为初次接触代码编程的你,是不是觉得Python程序除了“码”就是“字”即使是有趣的程序除了烧烧自己的脑,也吸引不到更多人的兴趣,用户体验值接近于0?那你可冤枉了Python,他可是人工智能界的编程语言大咖。今天这个游戏设计就先带领大家,简单体验一下,如何让Python程序图形化。一起来吧!设计我们的小游戏游戏设计思路:电脑随机出...

weixin_34214135的博客 1872

《Netty实战》阅读笔记

《Netty实战》阅读笔记

yzy_cb的博客 1780

DIY音乐播放器:用VS1053模块+Arduino打造你的专属MP3播放器(附完整代码)

本文详细介绍了如何使用VS1053音频解码模块与Arduino开发板,从零开始构建一个功能完备的桌面级MP3播放器。内容涵盖硬件架构设计、SPI总线共享、底层驱动编写、双缓冲区数据流管理以及用户交互实现,并提供完整的代码示例与性能优化建议,帮助创客打造高度可定制的专属音乐播放设备。

weixin_29189003的博客 287

netty实战笔记

《 Netty in action 》 netty实战笔记 目录 第一章 netty – 异步和事件驱动 第二章 第一个Netty程序 第三章 Netty的组件和设计

方小白 1250

格拉姆角场(GAF)实战:用Python实现时间序列图像化处理

本文深入解析了格拉姆角场(GAF)技术,这是一种将一维时间序列转化为二维图像特征的方法,以便利用卷积神经网络(CNN)等图像模型进行深度分析。文章通过Python实战代码,详细演示了GASF和GADF两种核心转换的实现过程,并探讨了其在时序数据分类任务中的应用,为故障预警、金融模式识别等场景提供了强大的图像驱动分析视角。

weixin_29079671的博客 273

UCIe物理层 —— 逻辑协议 (2)

本章开始主要介绍UCIe协议第四章,物理层逻辑定义和规范。如其他的通信协议一样,接口的物理层包含两个部分,逻辑子层和电气子层。其中逻辑层主要负责:1.定义接口信号和时序2. 定义发送端如何将上层数据分发到各个物理通道以及接收端如何把从各个通道收到的数据恢复成byte stream(Flit)。3. Broken Lane的repair和remap。4. 链路初始化,训练(training)和电源状态管理/切换。5. 扰码Scrambling和training sequence的产生。

m0_47581558的博客 1479

实战Netty集群

疯狂创客圈 Java 分布式聊天室【 亿级流量】实战系列之 -25【 博客园 总入口 】 1.写在前面 1.1 实战Netty集群的理由 Java基础练习中,一个重要的实战练习是: java的聊天程序。基本上,每一个java工程师,都有写过自己的聊天程序。 实现一个Java的分布式的聊天程序的分布式练习,同样非常重要的是。有以下几个方面的最重要作用: 1 体验高并发的程序的开发:从研...

weixin_30786617的博客 4406

Ultrascale/Ultrascale+ FPGA GTH IP及结构详解(一)

FPGA GTH Transceiver

houzi6320的博客 1万+

Netty的简介与实战

Netty的简介与实战

weixin_46619605的博客 1643

基于IEEE39节点系统的风力发电机组并网改造与稳定性研究

本文研究了基于IEEE39节点系统的风力发电机组并网改造与稳定性问题。首先将系统工作频率从60Hz转换为50Hz,并对同步发电机、变压器、线路和负荷参数进行相应调整。随后将30、32、34、37号节点的同步发电机替换为不同容量的永磁同步发电机(PMSG)和双馈感应发电机(DFIG),详细建立了两种风电机组的数学模型和控制策略。通过Simulink仿真验证,改造后的系统能够稳定运行并满足并网要求。研究成果为大规模风电并网系统仿真提供了参考,对提高电力系统可再生能源消纳能力具有重要意义。

huanghm88的专栏 110

YOLO11涨点优化:小目标检测 | 多头检测器提升小目标检测精度

引入多头检测器助力YOLO11,添加一个微小物体的检测头暴力提升小目标检测性能

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 4742

Netty实战中英文版

Netty实战中英文版 #链接: https://pan.baidu.com/s/1Ef7JP-7YpGkuFUmkyQYrnw 提取码: hpvg 复制这段内容后打开百度网盘手机App,操作更方便哦

LiJunqiang_0220的博客 512

ReAct 智能体 Agent:架构解析与实践拓展

ReAct 智能体 Agent 凭借其推理与行动协同的独特架构,在众多人工智能应用场景中展现出巨大的潜力。从智能办公到教育辅导,从智能家居到工业物联网,ReAct 智能体通过精准推理和高效行动,为用户提供了更加智能、便捷的服务体验。然而,在实际应用过程中,仍面临工具调用安全、模型持续学习、多智能体协作管理以及性能优化等多方面的挑战。通过合理的策略和技术创新,如强化工具审核机制、构建持续学习框架、设计高效协作协议和采用性能优化手段,我们有望逐步克服这些挑战,进一步提升 ReAct 智能体的性能和可靠性。

加入“Super Entity”,与全能开发团队共探AI智能体与数字人项目,开启前沿技术之旅。 1688

思维导图:《Netty实战》

Netty、Bootstrap、EventLoopGroup、ChannelPipeline、Channel、ChannelHandler、ChannelHandlerContext、ChannelFuture、ByteBuf

u010921136的博客 665

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

【网络编程】Netty实战入门详解

分享学习: Netty实战入门详解——让你彻底记住什么是Netty(看不懂你来找我)

marry44750的博客 362

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Essential Netty in Action 《Netty 实战(精髓)》

netty入门的资料: Essential Netty in Action 《Netty 实战(精髓)》 https://www.javajike.com/book/essential-netty-in-action/chapter3/d4bbd07aba1b02a019407d4ad8754143.html

zsd_31的专栏 389

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Netty实战入门详解——让你彻底记住什么是Netty(看不懂你来找我)

Netty 是基于 Java NIO 的异步事件驱动的网络应用框架,使用 Netty 可以快速开发网络应用,Netty 提供了高层次的抽象来简化 TCP 和 UDP 服务器的编程,但是你仍然可以使用底层的 API。Netty 的内部实现是很复杂的,但是 Netty 提供了简单易用的API从网络处理代码中解耦业务逻辑。Netty 是完全基于 NIO 实现的,所以整个 Netty 都是异步的。

2301_78843735的博客 1684

Netty实战入门教程

Netty 是一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端Netty 在 Java 网络应用框架中的地位就好比:Spring 框架在 JavaEE 开发中的地位以下的框架都使用了 Netty,因为它们有网络通信需求!Cassandra - nosql 数据库Spark - 大数据分布式计算框架Hadoop - 大数据分布式存储框架RocketMQ - ali 开源的消息队列ElasticSearch - 搜索引擎gRPC - rpc 框架。

SevenCoding的博客 757

netty长连接实战

1,准备好netty必须的jar <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.0.23.Final</version> </dependency> &l...

墨门新秀 3137
上一篇: 基于Netty的简单聊天室的实现
下一篇: 面向对象开发基本原则笔记-(理解记忆)
monkeyhlj
博客等级 码龄9年 1万+粉丝 184原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值