# nettydemo **Repository Path**: android100/nettydemo ## Basic Information - **Project Name**: nettydemo - **Description**: nettydemo - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-04-13 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [Netty 源码分析]() [浅析 Netty 实现心跳机制与断线重连](https://segmentfault.com/a/1190000006931568) [Netty Client 重连实现](http://www.importnew.com/25046.html) [Netty 断线重连解决方案](https://www.jianshu.com/p/c78b37a2ca47) [Netty实现心跳机制与断线重连](https://www.jianshu.com/p/1a28e48edd92) [Netty实现心跳检测与断线重连](https://segmentfault.com/a/1190000007432946) 消息推送一般的思路就是: 1.轮询(Pull)客户端定时的去询问服务器是否有新消息需要下发;确点很明显Android后台不停的访问网络费电还浪费流量。 2.推送(Push)服务端有新消息立即发送给客户端,这就没有时间的延迟,消息及时到达。 由于移动无线网络的特点,推送服务的心跳周期并不能设置的太长,否则长连接会被释放, 造成频繁的客户端重连,但是也不能设置太短,否则在当前缺乏统一心跳框架的机制下很容易导致信令风暴 (例如微信心跳信令风暴问题)。具体的心跳周期并没有统一的标准,180S也许是个不错的选择,微信为300S。 # 心跳 所谓心跳, 即在 TCP 长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保 TCP 连接的有效性. 在 Netty 中, 实现心跳机制的关键是 IdleStateHandler ``` public IdleStateHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds) { this((long)readerIdleTimeSeconds, (long)writerIdleTimeSeconds, (long)allIdleTimeSeconds, TimeUnit.SECONDS); } ``` 这里解释下三个参数的含义: readerIdleTimeSeconds: 读超时. 即当在指定的时间间隔内没有从 Channel 读取到数据时, 会触发一个 READER_IDLE 的 IdleStateEvent 事件. writerIdleTimeSeconds: 写超时. 即当在指定的时间间隔内没有数据写入到 Channel 时, 会触发一个 WRITER_IDLE 的 IdleStateEvent 事件. allIdleTimeSeconds: 读/写超时. 即当在指定的时间间隔内没有读或写操作时, 会触发一个 ALL_IDLE 的 IdleStateEvent 事件. 使用IdleStateHandler来实现心跳: Client端连接到Server端后,会循环执行一个任务: 随机等待几秒,然后ping一下Server端,即发送一个心跳包。 当等待的时间超过规定时间,将会发送失败,以为Server端在此之前已经主动断开连接了。 # Bootstrap——启动类 ``` public abstract class AbstractBootstrap, C extends Channel> implements Cloneable { //线程池 volatile EventLoopGroup group; //创建channel的工厂类 @SuppressWarnings("deprecation") private volatile ChannelFactory channelFactory; //本地地址 private volatile SocketAddress localAddress; //socket及其它的一些属性设置 private final Map, Object> options = new LinkedHashMap, Object>(); //附加属性设置 private final Map, Object> attrs = new LinkedHashMap, Object>(); //channel处理类 private volatile ChannelHandler handler; } ``` 1.客户端和服务端执行的逻辑不同,一个是connect一个是bind,但是最终都是通过channel来完成该操作的,即channel决定了连接的方式。 2.服务端不需要设置服务端的handler,其内置了一个ServerBoostrapAcceptor,主要设置了客户端的channel属性, 这段逻辑最终也是由服务端的channel的read相关方法控制的,即服务端的channel,read方法接收的是一个channel而不是一个byte。 3.所有的channel都需要注册到EventLoop中。 # TCP黏包/拆包 [Netty4实战 - TCP粘包&拆包解决方案](https://blog.csdn.net/a925907195/article/details/74942472) TCP是一个“流”协议,所谓流,就是没有界限的一长串二进制数据。TCP作为传输层协议并不不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分,所以在业务上认为是一个完整的包,可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。 粘包问题的解决策略 由于底层的TCP无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决。业界的主流协议的解决方案,可以归纳如下: 1. 消息定长,报文大小固定长度,例如每个报文的长度固定为200字节,如果不够空位补空格; 2. 包尾添加特殊分隔符,例如每条报文结束都添加回车换行符(例如FTP协议)或者指定特殊字符作为报文分隔符,接收方通过特殊分隔符切分报文区分; 3. 将消息分为消息头和消息体,消息头中包含表示信息的总长度(或者消息体长度)的字段; 4. 更复杂的自定义应用层协议。