Netty+Service+BroadCast实现TCP 长连接
https://ifeve.com/socket-channel/
https://mp.weixin.qq.com/s/HhwaXd8x7zONr8N1ojSnsQ
https://www.jianshu.com/p/f4ee6b1cd8c4
https://baijiahao.baidu.com/s?id=1652411987807894303&wfr=spider&for=pc
https://github.com/code4craft/netty-learning/blob/master/posts/ch1-overview.md
Netty:
传统的网络通信框架通常是开启一个子线程,在子线程中创建一个Socket连接,通过Socket连接去向服务端请求数据,在等待服务端返回数据的时候会发生阻塞,如果请求越来越多,那么因网络等待被阻塞的线程也会越来越多
为了解决上面的问题,提出了使用NIO实现的Netty网络框架,每次客户端请求,会创建一个SocketChannel,并且将其注册到Selector(多路复用器),Selector关注服务端数据的IO有没有到来,线程不需要等待IO,可以做自己的事情
基于NIO的Netty网络请求
Netty核心组件:
Channel:(Socket)
当客户端和服务端建立连接时会创建一个Channel,可以理解为Socket连接,负责基本的IO操作;
EventLoop:(监控+通知)
服务器发出消息称为出站
,服务器接收的消息称为入站
,消息的出站和入站会产生事件(Event),EventLoop用于监控和协调事件,在Netty中每一个channel都会分配一个EventLoop为其服务,一个EventLoop可以服务多个Channel;每一个EventLoop会占用一个线程,这个 Thread 会处理 EventLoop 上面发生的所有 IO 操作和事件;
EventLoopGroup:
EventLoopGroup是用于创建EventLoop的,EventLoopGroup中可以存放多个EventLoop
Netty实现单线程多任务核心思想:
EventLoop可以监控服务端的数据,当数据到达时会通知客户端去处理,在等待的时候,客户端线程可以去做别的事情;传统思想是一个Channel(Socket)对应一个Thread,Netty是一个EventLoop对应一个线程,而EventLoop可以对应多个Channel(Socket)
ChannelHandler:事件处理者
- ChannelInBoundHandler(入站事件处理)
- ChannelOutBoundHandler(出站事件处理)
每一次请求都会出发事件,事件由Handler处理,处理顺序由ChannelPipeline决定
ChannelPipeline: (事件排队)
ChannelPipeline为ChannelHandler提供了容器,pipeLine 保证了 handler 按照一定顺序处理事件,当事件发生后,会将数据按照一定的顺序通过pipeLine传给handler,同时,ChannelPipeline 也可以添加或者删除 ChannelHandler,管理整个队列。
ChannelHandlerContext : (传递消息给handler)
每当有 ChannelHandler 添加到 ChannelPipeline 时,同时会创建 ChannelHandlerContext 。ChannelHandlerContext 的主要功能是管理 ChannelHandler 和 ChannelPipeline 的交互。ChannelHandlerContext 参数贯穿 ChannelPipeline,将信息传递给每个 ChannelHandler
上述核心组件总结:
EventLoop & EventLoopGroup ChannelPipeline & ChannelHandlerContext
Bootstrap:
Bootstrap是netty的引导类,用于netty的配置和连接的建立;Bootstrap有两个实现类:
-
Bootstrap:
客户端引导 -
ServerBootstrap:
服务端引导
Bootstrap(客户端引导)需要一个 EventLoopGroup,但是 ServerBootstrap(服务端引导)则需要两个 EventLoopGroup。因为服务器需要两组不同的 Channel。第一组 ServerChannel 自身监听本地端口的套接字。第二组用来监听客户端请求的套接字。
Netty实现长连接
通过心跳机制,定时发送一个数据,配合Service+BroadCasetReceiver
,实现长连接实时推送股票的最新数据
由于公司的代码不能乱贴,就随便写写画画吧,大概说个意思
-
创建
bootstrap
对象配置netty,设置channel
类型,设置handler
顺序,添加自定义handler, -
bootstrap.connect()建立连接;
-
创建一个
Service
,在服务中根据业务推送相应的数据,同时注册一个广播接收器,在屏幕关闭时断开TCP连接,屏幕亮起时开启连接; -
实时推送的核心是自定义的这个handler,在自定义的handler中,重写
userEventTriggered()
,在这个方法中发送心跳包;
自定义handler:
public class MyHandler extends SimpleChannelInboundHandler {
@Override // 处理数据
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
}
@Override // 发送心跳包
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
super.userEventTriggered(ctx, evt);
}
}