├── .gitignore
├── README.md
├── netty-heartbeat-detection-demo
├── README.md
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── uifuture
│ │ └── hearbest
│ │ ├── cilent
│ │ ├── Client.java
│ │ └── ClientHandler.java
│ │ ├── codec
│ │ ├── FstSerializer.java
│ │ ├── TinyDecoder.java
│ │ └── TinyEncoder.java
│ │ ├── model
│ │ └── RequestInfo.java
│ │ ├── server
│ │ ├── Server.java
│ │ └── ServerHandler.java
│ │ └── utils
│ │ └── SigarUtil.java
│ └── resources
│ └── sigar
│ ├── libsigar-amd64-freebsd-6.so
│ ├── libsigar-amd64-linux.so
│ ├── libsigar-amd64-solaris.so
│ ├── libsigar-ia64-hpux-11.sl
│ ├── libsigar-ia64-linux.so
│ ├── libsigar-pa-hpux-11.sl
│ ├── libsigar-ppc-aix-5.so
│ ├── libsigar-ppc-linux.so
│ ├── libsigar-ppc64-aix-5.so
│ ├── libsigar-ppc64-linux.so
│ ├── libsigar-s390x-linux.so
│ ├── libsigar-sparc-solaris.so
│ ├── libsigar-sparc64-solaris.so
│ ├── libsigar-universal-macosx.dylib
│ ├── libsigar-universal64-macosx.dylib
│ ├── libsigar-x86-freebsd-5.so
│ ├── libsigar-x86-freebsd-6.so
│ ├── libsigar-x86-linux.so
│ ├── libsigar-x86-solaris.so
│ ├── sigar-amd64-winnt.dll
│ ├── sigar-x86-winnt.dll
│ └── sigar-x86-winnt.lib
├── netty-introduction-demo
├── README.md
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── uifuture
│ ├── client
│ ├── EchoClient.java
│ └── EchoClientHandler.java
│ └── server
│ ├── EchoServer.java
│ └── EchoServerHandler.java
├── netty-not-sticky-pack-demo
├── README.md
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── uifuture
│ └── unpack
│ ├── client
│ ├── Client.java
│ └── ClientHandler.java
│ ├── codec
│ └── FstSerializer.java
│ ├── model
│ └── User.java
│ ├── protocol
│ ├── Request.java
│ ├── Response.java
│ ├── TinyDecoder.java
│ └── TinyEncoder.java
│ └── server
│ ├── Server.java
│ └── ServerHandler.java
├── netty-serialization-demo
├── README.md
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── uifuture
│ ├── client
│ ├── Client.java
│ └── ClientHandler.java
│ ├── codec
│ └── FstSerializer.java
│ ├── model
│ └── User.java
│ ├── protocol
│ ├── Request.java
│ ├── Response.java
│ ├── TinyDecoder.java
│ └── TinyEncoder.java
│ └── server
│ ├── Server.java
│ └── ServerHandler.java
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | ### IntelliJ IDEA ###
23 | .idea
24 | *.iws
25 | *.iml
26 | *.ipr
27 |
28 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
29 | hs_err_pid*
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # netty-demo
2 | Netty Learning project
3 | 关于netty使用的一些实例
4 | netty-introduction-demo:Netty的入门实例
5 | netty-serialization-demo:Netty传输序列化对象
6 | netty-heartbeat-detection-demo:使用Netty进行服务器和客户端的心跳检测
7 | netty-not-sticky-pack-demo:Netty解决粘包问题,传输序列化对象
8 |
9 | 每个模块都是独立的项目,但是注意Jar包的依赖。
--------------------------------------------------------------------------------
/netty-heartbeat-detection-demo/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/README.md
--------------------------------------------------------------------------------
/netty-heartbeat-detection-demo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | netty-demo
9 | com.uifuture.netty
10 | 1.0-SNAPSHOT
11 |
12 | netty-heartbeat-detection-demo
13 |
14 |
15 |
16 | de.ruedigermoeller
17 | fst
18 | 2.52
19 |
20 |
21 |
22 |
23 | org.fusesource
24 | sigar
25 | 1.6.4
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/netty-heartbeat-detection-demo/src/main/java/com/uifuture/hearbest/cilent/Client.java:
--------------------------------------------------------------------------------
1 | /**
2 | * uifuture.com
3 | * Copyright (C) 2013-2018 All Rights Reserved.
4 | */
5 | package com.uifuture.hearbest.cilent;
6 |
7 | import com.uifuture.hearbest.codec.TinyDecoder;
8 | import com.uifuture.hearbest.codec.TinyEncoder;
9 | import com.uifuture.hearbest.model.RequestInfo;
10 | import io.netty.bootstrap.Bootstrap;
11 | import io.netty.channel.ChannelFuture;
12 | import io.netty.channel.ChannelInitializer;
13 | import io.netty.channel.EventLoopGroup;
14 | import io.netty.channel.nio.NioEventLoopGroup;
15 | import io.netty.channel.socket.SocketChannel;
16 | import io.netty.channel.socket.nio.NioSocketChannel;
17 |
18 | import java.net.InetSocketAddress;
19 |
20 | /**
21 | * @author chenhx
22 | * @version Client.java, v 0.1 2018-08-10 上午 9:57
23 | */
24 | public class Client {
25 | private final String host;
26 | private final int port;
27 |
28 | public Client(String host, int port) {
29 | this.host = host;
30 | this.port = port;
31 | }
32 |
33 | public static void main(String[] args) throws Exception {
34 | final String host = "127.0.0.1";
35 | final int port = 8081;
36 |
37 | new Client(host, port).start();
38 | }
39 |
40 | public void start() throws Exception {
41 | EventLoopGroup group = new NioEventLoopGroup();
42 | try {
43 | Bootstrap b = new Bootstrap();
44 | b.group(group)
45 | .channel(NioSocketChannel.class)
46 | .remoteAddress(new InetSocketAddress(host, port))
47 | .handler(new ChannelInitializer() {
48 | @Override
49 | public void initChannel(SocketChannel ch)
50 | throws Exception {
51 | ch.pipeline()
52 | // 添加编解码. 发送自定义的类型, 而Handler的方法接收的msg参数的实际类型也是相应的自定义类了
53 | .addLast(new TinyDecoder(RequestInfo.class))
54 | .addLast(new TinyEncoder(RequestInfo.class))
55 | .addLast(new ClientHandler());
56 | }
57 | });
58 |
59 | ChannelFuture f = b.connect().sync();
60 | f.channel().closeFuture().sync();
61 | } finally {
62 | group.shutdownGracefully().sync();
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/netty-heartbeat-detection-demo/src/main/java/com/uifuture/hearbest/cilent/ClientHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * uifuture.com
3 | * Copyright (C) 2013-2018 All Rights Reserved.
4 | */
5 | package com.uifuture.hearbest.cilent;
6 |
7 | import com.uifuture.hearbest.model.RequestInfo;
8 | import com.uifuture.hearbest.utils.SigarUtil;
9 | import io.netty.channel.ChannelHandlerContext;
10 | import io.netty.channel.SimpleChannelInboundHandler;
11 | import io.netty.util.ReferenceCountUtil;
12 | import org.hyperic.sigar.CpuPerc;
13 | import org.hyperic.sigar.Mem;
14 | import org.hyperic.sigar.Sigar;
15 |
16 | import java.net.InetAddress;
17 | import java.net.UnknownHostException;
18 | import java.util.HashMap;
19 | import java.util.concurrent.Executors;
20 | import java.util.concurrent.ScheduledExecutorService;
21 | import java.util.concurrent.ScheduledFuture;
22 | import java.util.concurrent.TimeUnit;
23 |
24 | /**
25 | * @author chenhx
26 | * @version ClientHandler.java, v 0.1 2018-08-10 上午 9:58
27 | */
28 | public class ClientHandler extends SimpleChannelInboundHandler {
29 | private static final String SUCCESS_KEY = "auth_success_key";
30 | /**
31 | * 开一个线程进行心跳包
32 | */
33 | private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
34 | /**
35 | * 定时任务
36 | */
37 | private ScheduledFuture> heartBeat;
38 | /**
39 | * 主动向服务器发送认证信息
40 | */
41 | private InetAddress addr;
42 |
43 | /**
44 | * 通道注册
45 | *
46 | * @param ctx
47 | * @throws Exception
48 | */
49 | @Override
50 | public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
51 | super.channelRegistered(ctx);
52 | }
53 |
54 | /**
55 | * 服务器的连接被建立后调用
56 | * 建立连接后该 channelActive() 方法被调用一次
57 | *
58 | * @param ctx
59 | */
60 | @Override
61 | public void channelActive(ChannelHandlerContext ctx) throws UnknownHostException {
62 | addr = InetAddress.getLocalHost();
63 | System.out.println("addr=" + addr);
64 | String ip = "192.168.21.89";
65 | String key = "1234";
66 | //证书
67 | String auth = ip + "," + key;
68 | // 发送认证
69 | ctx.writeAndFlush(auth);
70 | }
71 |
72 | @Override
73 | protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
74 | try {
75 | if (msg instanceof String) {
76 | String ret = (String) msg;
77 | if (SUCCESS_KEY.equals(ret)) {
78 | // 收到认证 确认信息,设置每隔5秒发送心跳消息
79 | this.heartBeat = this.scheduler.scheduleWithFixedDelay(new HeartBeatTask(ctx), 0, 5, TimeUnit.SECONDS);
80 | System.out.println("接收到信息:" + msg);
81 | } else {
82 | // 收到心跳包 确认信息
83 | System.out.println("接收到信息:" + msg);
84 | }
85 | }
86 | } finally {
87 | // 只读, 需要手动释放引用计数
88 | ReferenceCountUtil.release(msg);
89 | }
90 | }
91 |
92 | /**
93 | * 捕获异常时调用
94 | *
95 | * @param ctx
96 | * @param cause
97 | */
98 | @Override
99 | public void exceptionCaught(ChannelHandlerContext ctx,
100 | Throwable cause) {
101 | //记录错误日志并关闭 channel
102 | cause.printStackTrace();
103 | ctx.close();
104 | }
105 |
106 |
107 | private class HeartBeatTask implements Runnable {
108 | private final ChannelHandlerContext ctx;
109 | private Integer times = 0;
110 |
111 | public HeartBeatTask(final ChannelHandlerContext ctx) {
112 | this.ctx = ctx;
113 | }
114 |
115 | @Override
116 | public void run() {
117 | try {
118 | if (times++ > 10) {
119 | //取消定时任务
120 | closeHeartBeat();
121 | return;
122 | }
123 | System.out.println("第" + times + "次请求...");
124 | RequestInfo info = new RequestInfo();
125 | //ip
126 | info.setIp(addr.getHostAddress());
127 | Sigar sigar = SigarUtil.getInstance();
128 | //cpu prec
129 | CpuPerc cpuPerc = sigar.getCpuPerc();
130 | HashMap cpuPercMap = new HashMap<>();
131 | cpuPercMap.put("combined", cpuPerc.getCombined());
132 | cpuPercMap.put("user", cpuPerc.getUser());
133 | cpuPercMap.put("sys", cpuPerc.getSys());
134 | cpuPercMap.put("wait", cpuPerc.getWait());
135 | cpuPercMap.put("idle", cpuPerc.getIdle());
136 | // memory
137 | Mem mem = sigar.getMem();
138 | HashMap memoryMap = new HashMap<>();
139 | memoryMap.put("total", mem.getTotal() / 1024L / 1024L);
140 | memoryMap.put("used", mem.getUsed() / 1024L / 1024L);
141 | memoryMap.put("free", mem.getFree() / 1024L / 1024L);
142 | info.setCpuPercMap(cpuPercMap);
143 | info.setMemoryMap(memoryMap);
144 |
145 | ctx.writeAndFlush(info);
146 | } catch (Exception e) {
147 | e.printStackTrace();
148 | }
149 | }
150 |
151 | /**
152 | * 出现异常调用
153 | *
154 | * @param ctx
155 | * @param cause
156 | * @throws Exception
157 | */
158 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
159 | cause.printStackTrace();
160 | // 取消定时发送心跳包的任务
161 | if (heartBeat != null) {
162 | heartBeat.cancel(true);
163 | heartBeat = null;
164 | }
165 | ctx.fireExceptionCaught(cause);
166 | }
167 |
168 | /**
169 | * 取消定时任务
170 | */
171 | public void closeHeartBeat() {
172 | // 取消定时发送心跳包的任务
173 | if (heartBeat != null) {
174 | heartBeat.cancel(true);
175 | heartBeat = null;
176 | }
177 | }
178 | }
179 |
180 | }
--------------------------------------------------------------------------------
/netty-heartbeat-detection-demo/src/main/java/com/uifuture/hearbest/codec/FstSerializer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * uifuture.com
3 | * Copyright (C) 2013-2018 All Rights Reserved.
4 | */
5 | package com.uifuture.hearbest.codec;
6 |
7 | import org.nustaq.serialization.FSTConfiguration;
8 |
9 | /**
10 | * @author chenhx
11 | * @version FstSerializer.java, v 0.1 2018-08-08 下午 2:39
12 | */
13 | public class FstSerializer {
14 | private static FSTConfiguration conf = FSTConfiguration.createDefaultConfiguration();
15 |
16 | /**
17 | * 反序列化
18 | *
19 | * @param data
20 | * @param clazz
21 | * @param
22 | * @return
23 | */
24 | public static T deserialize(byte[] data, Class clazz) {
25 | return (T) conf.asObject(data);
26 | }
27 |
28 | /**
29 | * 序列化
30 | *
31 | * @param obj
32 | * @param
33 | * @return
34 | */
35 | public static byte[] serialize(T obj) {
36 | return conf.asByteArray(obj);
37 | }
38 | }
--------------------------------------------------------------------------------
/netty-heartbeat-detection-demo/src/main/java/com/uifuture/hearbest/codec/TinyDecoder.java:
--------------------------------------------------------------------------------
1 | package com.uifuture.hearbest.codec;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.handler.codec.ByteToMessageDecoder;
6 |
7 | import java.util.List;
8 |
9 | public class TinyDecoder extends ByteToMessageDecoder {
10 | private Class> genericClass;
11 |
12 | public TinyDecoder(Class> genericClass) {
13 | this.genericClass = genericClass;
14 | }
15 |
16 | /**
17 | * 解码
18 | *
19 | * @param ctx
20 | * @param in
21 | * @param out
22 | */
23 | @Override
24 | public final void decode(ChannelHandlerContext ctx, ByteBuf in, List