netty的心跳发送的重连,主要在client端。前面有关于自定义协议的demo:https://blog.csdn.net/zc_ad/article/details/83829620
其实客户端心跳发送用到的是IdleStateHandler,详细看代码你就会明白为什么。
//处理空闲状态事件的处理器
pipeline.addLast(new IdleStateHandler(6,7,8, TimeUnit.SECONDS));
在IdleStateHandler中前三个参数分别是:
1.当在6秒内收到消息,触发IdleStateEvent事件。
2.当在7秒内没有发送消息,触发IdleStateEvent事件。
3.当在8内没有接收到数据且在8秒内没有发送数据,触发IdleStateEvent事件。
下面是实现的代码,代码量有点多....:
常量数据:
/**
* Created by XiChuan on 2018-11-07.
*/
public class Constant {
public static final int HEAD = 0x76;
public static final String TYPE_PING = "PING";
public static final String TYPE_MESSAGE = "MESSAGE";
}
自定义协议:
/**
* Created by XiChuan on 2018-11-07.
*/
import java.util.Arrays;
/**
* <pre>
* 自己定义的协议
* 数据包格式
* +——----——+——-----——+——----——+
* |协议开始标志| 消息类型长度 | 消息类型 | 数据长度 | 数据 |
* +——----——+——-----——+——----——+
* 1.协议开始标志head_data,为int类型的数据,16进制表示为0X76
* 2.要传的协议类型长度(String的byte[]长度)
* 3.要传的协议类型(String)
* 4.传输数据的长度contentLength,int类型
* 5.要传输的数据
* </pre>
*/
public class MessageProtocol {
/**
* 消息的开头的信息标志
*/
private int headData = Constant.HEAD;
/**
* 消息类型长度
*/
private int typeLength;
/**
* 消息类型
*/
private String type;
/**
* 消息的长度
*/
private int contentLength;
/**
* 消息的内容
*/
private byte[] content;
/**
* 用于初始化,SmartCarProtocol
*
* @param contentLength
* 协议里面,消息数据的长度
* @param content
* 协议里面,消息的数据
*/
public MessageProtocol(int typeLength,String type,int contentLength, byte[] content) {
this.typeLength = typeLength;
this.type = type;
this.contentLength = contentLength;
this.content = content;
}
public int getHeadData() {
return headData;
}
public void setHeadData(int headData) {
this.headData = headData;
}
public int getTypeLength() {
return typeLength;
}
public void setTypeLength(int typeLength) {
this.typeLength = typeLength;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getContentLength() {
return contentLength;
}
public void setContentLength(int contentLength) {
this.contentLength = contentLength;
}
public byte[] getContent() {
return content;
}
public void setContent(byte[] content) {
this.content = content;
}
@Override
public String toString() {
return "MessageProtocol " +
"[head_data=" + headData
+", typeLength="+typeLength
+", type="+type
+ ", contentLength=" + contentLength
+ ", content=" + Arrays.toString(content) + "]";
}
}
定义解码器:
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.util.List;
/**
* Created by XiChuan on 2018-11-06.
*/
public class MessageProtocolDecoder extends ByteToMessageDecoder {
/**
* <pre>
* 协议开始的标准head_data,int类型,占据4个字节.
* 表示数据的长度contentLength,int类型,占据4个字节.
* </pre>
*/
public final int BASE_LENGTH = 4 + 4;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer,
List<Object> out) throws Exception {
// 可读长度必须大于基本长度
//System.out.println("buff的可读长度是:"+buffer.readableBytes());
if (buffer.readableBytes() >= BASE_LENGTH) {
// 防止socket字节流攻击
// 防止,客户端传来的数据过大
// 因为,太大的数据,是不合理的
if (buffer.readableBytes() > 2048) {
buffer.skipBytes(buffer.readableBytes());
}