compile 'org.msgpack:msgpack:0.6.12'
package com.zmm.netty4msgpacktest.domain;
import org.msgpack.annotation.Message;
@Message
public class DeviceValue {
private int type;
private int seatId;
private int speed;
private int angle;
public int getType() {
return type;
}
public DeviceValue() {
}
public void setType(int type) {
this.type = type;
}
public int getSeatId() {
return seatId;
}
public void setSeatId(int seatId) {
this.seatId = seatId;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getAngle() {
return angle;
}
public void setAngle(int angle) {
this.angle = angle;
}
@Override
public String toString() {
return "DeviceValue{" +
"type=" + type +
", seatId=" + seatId +
", speed=" + speed +
", angle=" + angle +
'}';
}
}
package com.zmm.netty4msgpacktest.domain;
public interface TypeData {
//模式
byte PING = 1;
byte PONG = 2;
byte CUSTOME = 3;
//*******************************
byte PING_SEAT = 100;
byte PONG_SEAT = 101;
byte SERVER_RESPONSE = 102;
byte SERVER_RESISTANT = 103;
}
package com.zmm.netty4msgpacktest.code;
import org.msgpack.MessagePack;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
public class MsgPackEncode extends MessageToByteEncoder<Object> {
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
MessagePack msgPack = new MessagePack();
byte[] raw = msgPack.write(msg);
out.writeBytes(raw);
}
}
package com.zmm.netty4msgpacktest.code;
import com.zmm.netty4msgpacktest.domain.DeviceValue;
import org.msgpack.MessagePack;
import java.util.List;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
public class MsgPackDecode extends MessageToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List
package com.zmm.netty4msgpacktest.common;
import com.zmm.netty4msgpacktest.domain.DeviceValue;
import com.zmm.netty4msgpacktest.domain.TypeData;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
public abstract class CustomHeartbeatHandler extends ChannelInboundHandlerAdapter {
protected String name;
private int heartbeatCount = 0;
public CustomHeartbeatHandler(String name) {
this.name = name;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
DeviceValue deviceValue = (DeviceValue) msg;
int type = deviceValue.getType();
System.out.println("CustomHeartbeatHandler type="+type);
switch (type){
case 1:
sendPongMsg(ctx);
break;
case 2:
System.out.println(name + " get pong msg from " + ctx.channel().remoteAddress());
break;
case 3:
handleData(ctx, msg);
break;
}
}
protected void sendPingMsg(ChannelHandlerContext context) {
DeviceValue deviceValue = new DeviceValue();
deviceValue.setType(TypeData.PING);
deviceValue.setSpeed(0);
deviceValue.setAngle(15);
deviceValue.setSeatId(TypeData.PING_SEAT);
context.channel().writeAndFlush(deviceValue);
heartbeatCount++;
System.out.println(name + " sent ping msg to " + context.channel().remoteAddress() + ", count: " + heartbeatCount);
}
private void sendPongMsg(ChannelHandlerContext context) {
DeviceValue deviceValue = new DeviceValue();
deviceValue.setType(TypeData.PONG);
deviceValue.setSpeed(0);
deviceValue.setAngle(15);
deviceValue.setSeatId(TypeData.PONG_SEAT);
context.channel().writeAndFlush(deviceValue);
heartbeatCount++;
System.out.println(name + " sent pong msg to " + context.channel().remoteAddress() + ", count: " + heartbeatCount);
}
protected abstract void handleData(ChannelHandlerContext channelHandlerContext, Object msg);
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
// IdleStateHandler 所产生的 IdleStateEvent 的处理逻辑.
if (evt instanceof IdleStateEvent) {
IdleStateEvent e = (IdleStateEvent) evt;
switch (e.state()) {
case READER_IDLE:
handleReaderIdle(ctx);
break;
case WRITER_IDLE:
handleWriterIdle(ctx);
break;
case ALL_IDLE:
handleAllIdle(ctx);
break;
default:
break;
}
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.err.println("---" + ctx.channel().remoteAddress() + " is active---");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.err.println("---" + ctx.channel().remoteAddress() + " is inactive---");
}
protected void handleReaderIdle(ChannelHandlerContext ctx) {
System.err.println("---READER_IDLE---");
}
protected void handleWriterIdle(ChannelHandlerContext ctx) {
System.err.println("---WRITER_IDLE---");
}
protected void handleAllIdle(ChannelHandlerContext ctx) {
System.err.println("---ALL_IDLE---");
}
}
package com.zmm.netty4msgpacktest.client;
import com.zmm.netty4msgpacktest.common.CustomHeartbeatHandler;
import com.zmm.netty4msgpacktest.domain.DeviceValue;
import com.zmm.netty4msgpacktest.domain.TypeData;
import io.netty.channel.ChannelHandlerContext;
public class ClientHandler extends CustomHeartbeatHandler {
private Client client;
public ClientHandler(Client client) {
super("client");
this.client = client;
}
@Override
protected void handleData(ChannelHandlerContext channelHandlerContext, Object msg) {
DeviceValue deviceValue = (DeviceValue) msg;
System.out.println("client 接收数据:"+deviceValue.toString());
// DeviceValue s = new DeviceValue();
// s.setType(TypeData.CUSTOME);
// s.setSpeed(0);
// s.setAngle(15);
// s.setSeatId(TypeData.SERVER_RESPONSE);
// channelHandlerContext.writeAndFlush(s);
}
@Override
protected void handleAllIdle(ChannelHandlerContext ctx) {
super.handleAllIdle(ctx);
sendPingMsg(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
client.doConnect();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println(name + " exception"+cause.toString());
}
}
package com.zmm.netty4msgpacktest.server;
import com.zmm.netty4msgpacktest.common.CustomHeartbeatHandler;
import com.zmm.netty4msgpacktest.domain.DeviceValue;
import com.zmm.netty4msgpacktest.domain.TypeData;
import io.netty.channel.ChannelHandlerContext;
public class ServerHandler extends CustomHeartbeatHandler {
public ServerHandler() {
super("server");
}
@Override
protected void handleData(ChannelHandlerContext channelHandlerContext, Object msg) {
DeviceValue deviceValue = (DeviceValue) msg;
System.out.println("server 接收数据:"+deviceValue.toString());
DeviceValue s = new DeviceValue();
s.setType(TypeData.CUSTOME);
s.setSpeed(0);
s.setAngle(15);
s.setSeatId(TypeData.SERVER_RESPONSE);
channelHandlerContext.writeAndFlush(s);
System.out.println("server 发送数据:"+s.toString());
}
@Override
protected void handleReaderIdle(ChannelHandlerContext ctx) {
super.handleReaderIdle(ctx);
System.err.println("---client " + ctx.channel().remoteAddress().toString() + " reader timeout, close it---");
ctx.close();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println(name+" exception"+cause.toString());
}
}
package com.zmm.netty4msgpacktest.client;
import com.zmm.netty4msgpacktest.code.MsgPackDecode;
import com.zmm.netty4msgpacktest.code.MsgPackEncode;
import com.zmm.netty4msgpacktest.domain.DeviceValue;
import com.zmm.netty4msgpacktest.domain.TypeData;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
public class Client {
private NioEventLoopGroup workGroup = new NioEventLoopGroup(4);
private Channel channel;
private Bootstrap bootstrap;
public static void main(String[] args) throws Exception {
Client client = new Client();
client.start();
client.sendData();
}
public void start() {
try {
bootstrap = new Bootstrap();
bootstrap
.group(workGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline p = socketChannel.pipeline();
p.addLast(new IdleStateHandler(0, 0, 5));
// p.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, -4, 0));
p.addLast(new MsgPackDecode());
p.addLast(new MsgPackEncode());
p.addLast(new ClientHandler(Client.this));
}
});
doConnect();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 重连机制,每隔2s重新连接一次服务器
*/
protected void doConnect() {
if (channel != null && channel.isActive()) {
return;
}
ChannelFuture future = bootstrap.connect("127.0.0.1", 12345);
future.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture futureListener) throws Exception {
if (futureListener.isSuccess()) {
channel = futureListener.channel();
System.out.println("Connect to server successfully!");
} else {
System.out.println("Failed to connect to server, try connect after 2s");
futureListener.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
doConnect();
}
}, 2, TimeUnit.SECONDS);
}
}
});
}
/**
* 发送数据 每隔2秒发送一次
* @throws Exception
*/
public void sendData() throws Exception {
Random random = new Random(System.currentTimeMillis());
for (int i = 0; i < 10000; i++) {
if (channel != null && channel.isActive()) {
DeviceValue deviceValue = new DeviceValue();
deviceValue.setType(TypeData.CUSTOME);
deviceValue.setAngle(i%15);
deviceValue.setSeatId(i%30);
deviceValue.setSpeed(i%120);
System.out.println("client 发送数据:"+deviceValue.toString());
channel.writeAndFlush(deviceValue);
}
Thread.sleep(random.nextInt(20000));
}
}
}
package com.zmm.netty4msgpacktest.server;
import com.zmm.netty4msgpacktest.code.MsgPackDecode;
import com.zmm.netty4msgpacktest.code.MsgPackEncode;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
public class Server {
public static void main(String[] args) {
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
NioEventLoopGroup workGroup = new NioEventLoopGroup(4);
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline p = socketChannel.pipeline();
p.addLast(new IdleStateHandler(10, 0, 0));
// p.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, -4, 0));
p.addLast(new MsgPackDecode());
p.addLast(new MsgPackEncode());
p.addLast(new ServerHandler());
}
});
Channel ch = bootstrap.bind(12345).sync().channel();
System.out.println("------Server Start------");
ch.closeFuture().sync();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
Github源码:Netty4MsgPackTest