├── .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 out) { 25 | int size = in.readableBytes(); 26 | byte[] data = new byte[size]; 27 | in.readBytes(data); 28 | Object obj = FstSerializer.deserialize(data, genericClass); 29 | out.add(obj); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/java/com/uifuture/hearbest/codec/TinyEncoder.java: -------------------------------------------------------------------------------- 1 | package com.uifuture.hearbest.codec; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandler; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.MessageToByteEncoder; 7 | 8 | /** 9 | * Encoder 10 | */ 11 | @ChannelHandler.Sharable 12 | public class TinyEncoder extends MessageToByteEncoder { 13 | private Class genericClass; 14 | 15 | public TinyEncoder(Class genericClass) { 16 | this.genericClass = genericClass; 17 | } 18 | 19 | /** 20 | * 编码 21 | * @param ctx 22 | * @param in 23 | * @param out 24 | * @throws Exception 25 | */ 26 | @Override 27 | public void encode(ChannelHandlerContext ctx, Object in, ByteBuf out) { 28 | byte[] data = FstSerializer.serialize(in); 29 | out.writeBytes(data); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/java/com/uifuture/hearbest/model/RequestInfo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.hearbest.model; 6 | 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | import java.util.HashMap; 11 | 12 | /** 13 | * @author chenhx 14 | * @version RequestInfo.java, v 0.1 2018-08-10 上午 9:50 15 | */ 16 | @Data 17 | public class RequestInfo implements Serializable { 18 | /** 19 | * 以ip为标识 20 | */ 21 | private String ip; 22 | private HashMap cpuPercMap; 23 | private HashMap memoryMap; 24 | } -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/java/com/uifuture/hearbest/server/Server.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.hearbest.server; 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.ServerBootstrap; 11 | import io.netty.channel.ChannelFuture; 12 | import io.netty.channel.ChannelInitializer; 13 | import io.netty.channel.ChannelOption; 14 | import io.netty.channel.nio.NioEventLoopGroup; 15 | import io.netty.channel.socket.SocketChannel; 16 | import io.netty.channel.socket.nio.NioServerSocketChannel; 17 | 18 | /** 19 | * @author chenhx 20 | * @version Server.java, v 0.1 2018-08-10 上午 9:51 21 | */ 22 | public class Server { 23 | 24 | private final int port; 25 | 26 | public Server(int port) { 27 | this.port = port; 28 | } 29 | 30 | public static void main(String[] args) throws Exception { 31 | int port = 8081; 32 | new Server(port).start(); 33 | } 34 | 35 | public void start() throws Exception { 36 | NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); 37 | NioEventLoopGroup workerGroup = new NioEventLoopGroup(); 38 | try { 39 | ServerBootstrap b = new ServerBootstrap(); 40 | b.group(bossGroup, workerGroup) 41 | .channel(NioServerSocketChannel.class) 42 | .childHandler(new ChannelInitializer() { 43 | @Override 44 | public void initChannel(SocketChannel ch) { 45 | ch.pipeline() 46 | // 添加编解码. 发送自定义的类型, 而Handler的方法接收的msg参数的实际类型也是相应的自定义类了 47 | .addLast(new TinyDecoder(RequestInfo.class)) 48 | .addLast(new TinyEncoder(RequestInfo.class)) 49 | .addLast(new ServerHandler()); 50 | } 51 | }) 52 | .option(ChannelOption.SO_BACKLOG, 128) 53 | .childOption(ChannelOption.SO_KEEPALIVE, true); 54 | ChannelFuture f = b.bind(port).sync(); 55 | System.out.println(Server.class.getName() + " started and listen on " + f.channel().localAddress()); 56 | f.channel().closeFuture().sync(); 57 | } finally { 58 | //释放 channel 和 块,直到它被关闭 59 | bossGroup.shutdownGracefully(); 60 | workerGroup.shutdownGracefully(); 61 | } 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/java/com/uifuture/hearbest/server/ServerHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.hearbest.server; 6 | 7 | import com.uifuture.hearbest.model.RequestInfo; 8 | import io.netty.channel.ChannelFutureListener; 9 | import io.netty.channel.ChannelHandlerContext; 10 | import io.netty.channel.SimpleChannelInboundHandler; 11 | import io.netty.util.internal.StringUtil; 12 | 13 | import java.util.HashMap; 14 | import java.util.HashSet; 15 | import java.util.Set; 16 | 17 | /** 18 | * @author chenhx 19 | * @version ServerHandler.java, v 0.1 2018-08-08 下午 2:52 20 | */ 21 | public class ServerHandler extends SimpleChannelInboundHandler { 22 | private static final String SUCCESS_KEY = "auth_success_key"; 23 | private static HashMap AUTH_IP_MAP = new HashMap<>(); 24 | private static Set AUTH_IP_SET = new HashSet<>(); 25 | 26 | static { 27 | AUTH_IP_MAP.put("192.168.21.89", "1234"); 28 | } 29 | 30 | /** 31 | * 进行认证 32 | * 在这里是根据ip和密码进行认证。也可以用账号和密码进行认证获取进行签名等等 33 | * 34 | * @param ctx 35 | * @param msg 36 | * @return 37 | */ 38 | private boolean auth(ChannelHandlerContext ctx, Object msg) { 39 | String[] ret = ((String) msg).split(","); 40 | String auth = AUTH_IP_MAP.get(ret[0]); 41 | if (!StringUtil.isNullOrEmpty(auth) && auth.equals(ret[1])) { 42 | // 认证成功, 返回确认信息 43 | ctx.writeAndFlush(SUCCESS_KEY); 44 | //添加到已认证机器上 45 | AUTH_IP_SET.add(ret[0]); 46 | return true; 47 | } else { 48 | ctx.writeAndFlush("auth failure !").addListener(ChannelFutureListener.CLOSE); 49 | return false; 50 | } 51 | } 52 | 53 | @Override 54 | public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { 55 | if (msg instanceof String) { 56 | auth(ctx, msg); 57 | } else if (msg instanceof RequestInfo) { 58 | RequestInfo info = (RequestInfo) msg; 59 | if (!AUTH_IP_SET.contains(info.getIp())) { 60 | System.out.println("尚未认证的机器..." + info.getIp()); 61 | return; 62 | } 63 | System.out.println("--------------------" + System.currentTimeMillis() + "------------------------"); 64 | System.out.println("当前主机ip为: " + info.getIp()); 65 | System.out.println("当前主机cpu情况: "); 66 | HashMap cpu = info.getCpuPercMap(); 67 | System.out.println("总使用率: " + cpu.get("combined")); 68 | System.out.println("用户使用率: " + cpu.get("user")); 69 | System.out.println("系统使用率: " + cpu.get("sys")); 70 | System.out.println("等待率: " + cpu.get("wait")); 71 | System.out.println("空闲率: " + cpu.get("idle")); 72 | 73 | System.out.println("当前主机memory情况: "); 74 | HashMap memory = info.getMemoryMap(); 75 | System.out.println("内存总量: " + memory.get("total")); 76 | System.out.println("当前内存使用量: " + memory.get("used")); 77 | System.out.println("当前内存剩余量: " + memory.get("free")); 78 | System.out.println("--------------------------------------------"); 79 | 80 | ctx.writeAndFlush("success"); 81 | } else { 82 | ctx.writeAndFlush("error").addListener(ChannelFutureListener.CLOSE); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/java/com/uifuture/hearbest/utils/SigarUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.hearbest.utils; 6 | 7 | import org.hyperic.sigar.Sigar; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.net.URL; 12 | import java.util.MissingResourceException; 13 | 14 | /** 15 | * Sigar工具类 16 | * 获取Sigar单例 17 | * @author chenhx 18 | * @version SigarUtil.java, v 0.1 2018-08-10 上午 10:20 19 | */ 20 | public class SigarUtil { 21 | static { 22 | // Linux MacOS 分隔符 : Windows 是; 23 | String osName = System.getProperty("os.name", "generic").toLowerCase(); 24 | String splitSymbol = osName.contains("win") ? ";" : ":"; 25 | 26 | // 寻找 classpath 根目录下的 sigar 文件夹 27 | URL sigarURL = SigarUtil.class.getResource("/sigar"); 28 | if (null == sigarURL) { 29 | // 找不到抛异常 30 | throw new MissingResourceException("miss classpath:/sigar folder", SigarUtil.class.getName(), "classpath:/sigar"); 31 | } 32 | File classPath = new File(sigarURL.getFile()); 33 | String oldLibPath = System.getProperty("java.library.path"); 34 | try { 35 | // 追加库路径 36 | String newLibPath = oldLibPath + splitSymbol + classPath.getCanonicalPath(); 37 | System.setProperty("java.library.path", newLibPath); 38 | } catch (IOException e) { 39 | e.printStackTrace(); 40 | } 41 | } 42 | 43 | public static Sigar getInstance() { 44 | return SingleSigar.SIGAR; 45 | } 46 | 47 | private static class SingleSigar { 48 | private static final Sigar SIGAR = new Sigar(); 49 | } 50 | } -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-amd64-freebsd-6.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-amd64-freebsd-6.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-amd64-linux.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-amd64-linux.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-amd64-solaris.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-amd64-solaris.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ia64-hpux-11.sl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ia64-hpux-11.sl -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ia64-linux.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ia64-linux.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-pa-hpux-11.sl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-pa-hpux-11.sl -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ppc-aix-5.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ppc-aix-5.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ppc-linux.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ppc-linux.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ppc64-aix-5.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ppc64-aix-5.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ppc64-linux.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-ppc64-linux.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-s390x-linux.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-s390x-linux.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-sparc-solaris.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-sparc-solaris.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-sparc64-solaris.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-sparc64-solaris.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-universal-macosx.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-universal-macosx.dylib -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-universal64-macosx.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-universal64-macosx.dylib -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-x86-freebsd-5.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-x86-freebsd-5.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-x86-freebsd-6.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-x86-freebsd-6.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-x86-linux.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-x86-linux.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-x86-solaris.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/libsigar-x86-solaris.so -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/sigar-amd64-winnt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/sigar-amd64-winnt.dll -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/sigar-x86-winnt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/sigar-x86-winnt.dll -------------------------------------------------------------------------------- /netty-heartbeat-detection-demo/src/main/resources/sigar/sigar-x86-winnt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-heartbeat-detection-demo/src/main/resources/sigar/sigar-x86-winnt.lib -------------------------------------------------------------------------------- /netty-introduction-demo/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-introduction-demo/README.md -------------------------------------------------------------------------------- /netty-introduction-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | netty-demo 7 | com.uifuture.netty 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | netty-introduction-demo 13 | 14 | 15 | -------------------------------------------------------------------------------- /netty-introduction-demo/src/main/java/com/uifuture/client/EchoClient.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.client; 6 | 7 | import io.netty.bootstrap.Bootstrap; 8 | import io.netty.channel.ChannelFuture; 9 | import io.netty.channel.ChannelInitializer; 10 | import io.netty.channel.EventLoopGroup; 11 | import io.netty.channel.nio.NioEventLoopGroup; 12 | import io.netty.channel.socket.SocketChannel; 13 | import io.netty.channel.socket.nio.NioSocketChannel; 14 | 15 | import java.net.InetSocketAddress; 16 | 17 | /** 18 | * 连接服务器。通过host和port 19 | * 20 | * @author chenhx 21 | * @version EchoClient.java, v 0.1 2018-07-19 上午 9:58 22 | */ 23 | public class EchoClient { 24 | 25 | private final String host; 26 | private final int port; 27 | 28 | public EchoClient(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 EchoClient(host, port).start(); 38 | } 39 | 40 | public void start() throws Exception { 41 | EventLoopGroup group = new NioEventLoopGroup(); 42 | try { 43 | Bootstrap b = new Bootstrap(); 44 | //指定 EventLoopGroup 来处理客户端事件。由于我们使用 NIO 传输,所以用到了 NioEventLoopGroup 的实现 45 | b.group(group) 46 | .channel(NioSocketChannel.class) 47 | //设置服务器的地址和端口 48 | .remoteAddress(new InetSocketAddress(host, port)) 49 | //当建立一个连接和一个新的通道时,创建添加到 EchoClientHandler 实例 到 channel pipeline 50 | .handler(new ChannelInitializer() { 51 | @Override 52 | public void initChannel(SocketChannel ch) 53 | throws Exception { 54 | ch.pipeline().addLast( 55 | new EchoClientHandler()); 56 | } 57 | }); 58 | 59 | //连接到远程;等待连接完成 也可以在这里设置服务器地址和端口 60 | ChannelFuture f = b.connect().sync(); 61 | //阻塞直到 Channel 关闭 62 | f.channel().closeFuture().sync(); 63 | } finally { 64 | //调用 shutdownGracefully() 来关闭线程池和释放所有资源 65 | group.shutdownGracefully().sync(); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /netty-introduction-demo/src/main/java/com/uifuture/client/EchoClientHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.client; 6 | 7 | import io.netty.buffer.ByteBuf; 8 | import io.netty.buffer.Unpooled; 9 | import io.netty.channel.ChannelHandler; 10 | import io.netty.channel.ChannelHandlerContext; 11 | import io.netty.channel.SimpleChannelInboundHandler; 12 | import io.netty.util.CharsetUtil; 13 | 14 | /** 15 | * @author chenhx 16 | * @version EchoClientHandler.java, v 0.1 2018-07-19 上午 9:40 17 | */ 18 | @ChannelHandler.Sharable 19 | public class EchoClientHandler extends SimpleChannelInboundHandler { 20 | /** 21 | * 服务器的连接被建立后调用 22 | * 建立连接后该 channelActive() 方法被调用一次 23 | * 24 | * @param ctx 25 | */ 26 | @Override 27 | public void channelActive(ChannelHandlerContext ctx) { 28 | //当被通知该 channel 是活动的时候就发送信息 29 | ctx.writeAndFlush(Unpooled.copiedBuffer("Hello Netty! " + Long.toString(System.currentTimeMillis()), 30 | CharsetUtil.UTF_8)); 31 | } 32 | 33 | /** 34 | * 从服务器接收到数据调用 35 | * 36 | * @param ctx 37 | * @param in 38 | */ 39 | @Override 40 | public void channelRead0(ChannelHandlerContext ctx, 41 | ByteBuf in) { 42 | System.out.println("服务器发来消息: " + in.toString(CharsetUtil.UTF_8)); 43 | } 44 | 45 | /** 46 | * 捕获异常时调用 47 | * 48 | * @param ctx 49 | * @param cause 50 | */ 51 | @Override 52 | public void exceptionCaught(ChannelHandlerContext ctx, 53 | Throwable cause) { 54 | //记录错误日志并关闭 channel 55 | cause.printStackTrace(); 56 | ctx.close(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /netty-introduction-demo/src/main/java/com/uifuture/server/EchoServer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.server; 6 | 7 | import io.netty.bootstrap.ServerBootstrap; 8 | import io.netty.channel.ChannelFuture; 9 | import io.netty.channel.ChannelInitializer; 10 | import io.netty.channel.ChannelOption; 11 | import io.netty.channel.nio.NioEventLoopGroup; 12 | import io.netty.channel.socket.SocketChannel; 13 | import io.netty.channel.socket.nio.NioServerSocketChannel; 14 | 15 | import java.net.InetSocketAddress; 16 | 17 | /** 18 | * 配置服务器的启动代码。最少需要设置服务器绑定的端口,用来监听连接请求。 19 | * 20 | * @author chenhx 21 | * @version EchoServer.java, v 0.1 2018-07-19 上午 9:35 22 | */ 23 | public class EchoServer { 24 | 25 | private final int port; 26 | 27 | public EchoServer(int port) { 28 | this.port = port; 29 | } 30 | 31 | public static void main(String[] args) throws Exception { 32 | //设置端口值 33 | int port = 8081; 34 | //呼叫服务器的 start() 方法 35 | new EchoServer(port).start(); 36 | } 37 | 38 | public void start() throws Exception { 39 | //Netty内部都是通过线程在处理各种数据,EventLoopGroup就是用来管理调度他们的,注册Channel,管理他们的生命周期。 40 | //NioEventLoopGroup是一个处理I/O操作的多线程事件循环 41 | //bossGroup作为boss,接收传入连接 42 | //因为bossGroup仅接收客户端连接,不做复杂的逻辑处理,为了尽可能减少资源的占用,取值越小越好. 43 | NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); 44 | //workerGroup作为worker,处理boss接收的连接的流量和将接收的连接注册进入这个worke 45 | NioEventLoopGroup workerGroup = new NioEventLoopGroup(); 46 | try { 47 | //ServerBootstrap负责建立服务端 48 | //你可以直接使用Channel去建立服务端,但是大多数情况下你无需做这种乏味的事情 49 | ServerBootstrap b = new ServerBootstrap(); 50 | b.group(bossGroup, workerGroup) 51 | //指定使用NioServerSocketChannel产生一个Channel用来接收连接 指定NIO的模式 NioServerSocketChannel对应TCP, NioDatagramChannel对应UDP 52 | .channel(NioServerSocketChannel.class) 53 | //设置 socket 地址使用所选的端口 54 | .localAddress(new InetSocketAddress(port)) 55 | //ChannelInitializer用于配置一个新的Channel 56 | //用于向你的Channel当中添加ChannelInboundHandler的实现 57 | //添加 EchoServerHandler 到 Channel 的 ChannelPipeline 58 | .childHandler(new ChannelInitializer() { 59 | @Override 60 | public void initChannel(SocketChannel ch) { 61 | //ChannelPipeline用于存放管理ChannelHandel 62 | //ChannelHandler用于处理请求响应的业务逻辑相关代码 63 | // //配置通信数据的处理逻辑, 可以addLast多个 64 | ch.pipeline().addLast( 65 | new EchoServerHandler()); 66 | } 67 | })//对Channel进行一些配置 68 | //注意以下是socket的标准参数 69 | //BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。 70 | //Option是为了NioServerSocketChannel设置的,用来接收传入连接的 设置TCP缓冲区 71 | .option(ChannelOption.SO_BACKLOG, 128) 72 | //保持连接 73 | //是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。 74 | //childOption是用来给父级ServerChannel之下的Channels设置参数的 75 | .childOption(ChannelOption.SO_KEEPALIVE, true); 76 | //绑定的服务器;sync 等待服务器关闭 ,也可以在该处再绑定端口。 bind返回future(异步), 加上sync阻塞在获取连接处 77 | ChannelFuture f = b.bind().sync(); 78 | System.out.println(EchoServer.class.getName() + " started and listen on " + f.channel().localAddress()); 79 | //sync()会同步等待连接操作结果,用户线程将在此wait(),直到连接操作完成之后,线程被notify(),用户代码继续执行 80 | //closeFuture()当Channel关闭时返回一个ChannelFuture,用于链路检测 81 | f.channel().closeFuture().sync(); 82 | } finally { 83 | //释放 channel 和 块,直到它被关闭 84 | bossGroup.shutdownGracefully(); 85 | workerGroup.shutdownGracefully(); 86 | } 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /netty-introduction-demo/src/main/java/com/uifuture/server/EchoServerHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.server; 6 | 7 | import io.netty.buffer.ByteBuf; 8 | import io.netty.buffer.Unpooled; 9 | import io.netty.channel.ChannelFutureListener; 10 | import io.netty.channel.ChannelHandler; 11 | import io.netty.channel.ChannelHandlerContext; 12 | import io.netty.channel.ChannelInboundHandlerAdapter; 13 | import io.netty.util.CharsetUtil; 14 | 15 | /** 16 | * 处理服务器端通道 17 | * ChannelInboundHandlerAdapter继承自ChannelHandlerAdapter,实现了ChannelInboundHandler接口 18 | * ChannelInboundHandler接口提供了不同的事件处理方法,可进行重写 19 | * 实现了服务器的业务逻辑,决定了连接创建后和接收到信息后该如何处理 20 | * 21 | * @author chenhx 22 | * @version DiscardServerHandler.java, v 0.1 2018-07-13 下午 4:05 23 | */ 24 | 25 | //Sharable注解 标识这类的实例之间可以在 channel 里面共享 26 | @ChannelHandler.Sharable 27 | public class EchoServerHandler extends ChannelInboundHandlerAdapter { 28 | /** 29 | * 每个信息入站都会调用 30 | * 接收数据进行处理 31 | * 事件处理程序方法。每当从客户端接收到新数据时,使用该方法来接收客户端的消息。 在此示例中,接收到的消息的类型为ByteBuf。 32 | * 33 | * @param ctx 34 | * @param msg 35 | * @throws Exception 36 | */ 37 | @Override 38 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 39 | ByteBuf in = (ByteBuf) msg; 40 | System.out.println("客户端发来消息: " + in.toString(CharsetUtil.UTF_8)); 41 | //ChannelHandlerContext提供各种不同的操作用于触发不同的I/O时间和操作 42 | //调用write方法来逐字返回接收到的信息 43 | //这里我们不需要调用释放,因为Netty会在写的时候自动释放 44 | //只调用write是不会释放的,它会缓存,直到调用flush 45 | //将所接收的消息返回给发送者。注意,这还没有冲刷数据 46 | ctx.write(in); 47 | } 48 | 49 | /** 50 | * 当前读操作读取的最后一个消息被channelRead()方法消费时调用. 如果ChannelOption.AUTO_READ 属性被设置为off, 51 | * 不会再尝试从当前channel中读取inbound数据, 直到ChannelHandlerContext.read()方法被调用. 52 | * @param ctx 53 | * @throws Exception 54 | */ 55 | @Override 56 | public void channelReadComplete(ChannelHandlerContext ctx) { 57 | System.out.println("channel 通道读取完成"); 58 | //冲刷所有待审消息到远程节点。关闭通道后,操作完成 59 | //第一种写法 写一个空的buf,并刷新写出区域。完成后关闭sock channel连接。 60 | ctx.writeAndFlush(Unpooled.EMPTY_BUFFER) 61 | .addListener(ChannelFutureListener.CLOSE); 62 | //ctx.flush(); // 第二种方法:在client端关闭channel连接,这样的话,会触发两次channelReadComplete方法。 63 | //ctx.flush().close().sync(); // 第三种:改成这种写法也可以,但是这中写法,没有第一种方法的好。 64 | } 65 | 66 | /** 67 | * 读操作时捕获到异常时调用 68 | * 69 | * @param ctx 70 | * @param cause 71 | */ 72 | @Override 73 | public void exceptionCaught(ChannelHandlerContext ctx, 74 | Throwable cause) { 75 | //打印异常堆栈跟踪 76 | cause.printStackTrace(); 77 | //关闭通道 78 | ctx.close(); 79 | } 80 | 81 | 82 | } -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-not-sticky-pack-demo/README.md -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | netty-demo 7 | com.uifuture.netty 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | netty-not-sticky-pack-demo 13 | 14 | 15 | 16 | 17 | de.ruedigermoeller 18 | fst 19 | 2.52 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/src/main/java/com/uifuture/unpack/client/Client.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.unpack.client; 6 | 7 | import com.uifuture.unpack.protocol.Request; 8 | import com.uifuture.unpack.protocol.Response; 9 | import com.uifuture.unpack.protocol.TinyDecoder; 10 | import com.uifuture.unpack.protocol.TinyEncoder; 11 | import io.netty.bootstrap.Bootstrap; 12 | import io.netty.channel.ChannelFuture; 13 | import io.netty.channel.ChannelInitializer; 14 | import io.netty.channel.EventLoopGroup; 15 | import io.netty.channel.nio.NioEventLoopGroup; 16 | import io.netty.channel.socket.SocketChannel; 17 | import io.netty.channel.socket.nio.NioSocketChannel; 18 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 19 | 20 | import java.net.InetSocketAddress; 21 | 22 | /** 23 | * @author chenhx 24 | * @version Client.java, v 0.1 2018-08-08 下午 3:07 25 | */ 26 | public class Client { 27 | private final String host; 28 | private final int port; 29 | 30 | public Client(String host, int port) { 31 | this.host = host; 32 | this.port = port; 33 | } 34 | 35 | public static void main(String[] args) throws Exception { 36 | final String host = "127.0.0.1"; 37 | final int port = 8081; 38 | 39 | new Client(host, port).start(); 40 | } 41 | 42 | public void start() throws Exception { 43 | EventLoopGroup group = new NioEventLoopGroup(); 44 | try { 45 | Bootstrap b = new Bootstrap(); 46 | b.group(group) 47 | .channel(NioSocketChannel.class) 48 | .remoteAddress(new InetSocketAddress(host, port)) 49 | .handler(new ChannelInitializer() { 50 | @Override 51 | public void initChannel(SocketChannel ch) 52 | throws Exception { 53 | ch.pipeline() 54 | .addLast(new TinyEncoder(Request.class)) 55 | .addLast(new LengthFieldBasedFrameDecoder(1024 * 1024, 0, 4, 0, 0)) 56 | // 添加编解码. 发送自定义的类型, 而Handler的方法接收的msg参数的实际类型也是相应的自定义类了 57 | .addLast(new TinyDecoder(Response.class)) 58 | .addLast(new ClientHandler()); 59 | } 60 | }); 61 | 62 | ChannelFuture f = b.connect().sync(); 63 | f.channel().closeFuture().sync(); 64 | } finally { 65 | group.shutdownGracefully().sync(); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/src/main/java/com/uifuture/unpack/client/ClientHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.unpack.client; 6 | 7 | import com.uifuture.unpack.model.User; 8 | import com.uifuture.unpack.protocol.Request; 9 | import com.uifuture.unpack.protocol.Response; 10 | import io.netty.channel.ChannelHandlerContext; 11 | import io.netty.channel.SimpleChannelInboundHandler; 12 | 13 | /** 14 | * @author chenhx 15 | * @version ClientHandler.java, v 0.1 2018-08-08 下午 3:07 16 | */ 17 | public class ClientHandler extends SimpleChannelInboundHandler { 18 | 19 | /** 20 | * 通道注册 21 | * 22 | * @param ctx 23 | * @throws Exception 24 | */ 25 | @Override 26 | public void channelRegistered(ChannelHandlerContext ctx) throws Exception { 27 | super.channelRegistered(ctx); 28 | } 29 | 30 | /** 31 | * 服务器的连接被建立后调用 32 | * 建立连接后该 channelActive() 方法被调用一次 33 | * 34 | * @param ctx 35 | */ 36 | @Override 37 | public void channelActive(ChannelHandlerContext ctx) { 38 | Request request = new Request(); 39 | request.setRequestId(3L); 40 | User user = new User(); 41 | user.setUsername("测试客户端"); 42 | user.setPassword("4567"); 43 | user.setAge(21); 44 | request.setParameter(user); 45 | //当被通知该 channel 是活动的时候就发送信息 46 | ctx.writeAndFlush(request); 47 | } 48 | 49 | @Override 50 | protected void channelRead0(ChannelHandlerContext ctx, Response response) throws Exception { 51 | System.out.println("服务器发来消息 : " + response); 52 | } 53 | 54 | /** 55 | * 捕获异常时调用 56 | * 57 | * @param ctx 58 | * @param cause 59 | */ 60 | @Override 61 | public void exceptionCaught(ChannelHandlerContext ctx, 62 | Throwable cause) { 63 | //记录错误日志并关闭 channel 64 | cause.printStackTrace(); 65 | ctx.close(); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/src/main/java/com/uifuture/unpack/codec/FstSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.unpack.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-not-sticky-pack-demo/src/main/java/com/uifuture/unpack/model/User.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.unpack.model; 6 | 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * 传输测试的实体类 13 | * 14 | * @author chenhx 15 | * @version User.java, v 0.1 2018-08-08 下午 3:14 16 | */ 17 | @Data 18 | public class User implements Serializable { 19 | private static final long serialVersionUID = -5135011481747489263L; 20 | private String username; 21 | private String password; 22 | private Integer age; 23 | } -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/src/main/java/com/uifuture/unpack/protocol/Request.java: -------------------------------------------------------------------------------- 1 | package com.uifuture.unpack.protocol; 2 | 3 | 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * 请求数据 10 | */ 11 | @Data 12 | public class Request implements Serializable { 13 | private static final long serialVersionUID = -2747321595912488569L; 14 | private Long requestId; 15 | private String className; 16 | private String methodName; 17 | private Class parameterType; 18 | private Object parameter; 19 | } -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/src/main/java/com/uifuture/unpack/protocol/Response.java: -------------------------------------------------------------------------------- 1 | package com.uifuture.unpack.protocol; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 响应数据 9 | */ 10 | @Data 11 | public class Response implements Serializable { 12 | private static final long serialVersionUID = -3136380221020337915L; 13 | private Long requestId; 14 | private String error; 15 | private Object result; 16 | } 17 | -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/src/main/java/com/uifuture/unpack/protocol/TinyDecoder.java: -------------------------------------------------------------------------------- 1 | package com.uifuture.unpack.protocol; 2 | 3 | import com.uifuture.unpack.codec.FstSerializer; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.ByteToMessageDecoder; 7 | 8 | import java.util.List; 9 | 10 | public class TinyDecoder extends ByteToMessageDecoder { 11 | /** 12 | * 头部长度字节数 13 | * 由于在TinyEncoder的encode方法中使用的是writeInt,int为4个字节 14 | */ 15 | private Integer HEAD_LENGTH = 4; 16 | private Class genericClass; 17 | 18 | public TinyDecoder(Class genericClass) { 19 | this.genericClass = genericClass; 20 | } 21 | 22 | /** 23 | * 解码 24 | * 25 | * @param ctx 26 | * @param in 27 | * @param out 28 | */ 29 | @Override 30 | public final void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { 31 | //头部信息是int类型,长度是4,所以信息长度不可能小于4的 32 | if (in.readableBytes() < HEAD_LENGTH) { 33 | return; 34 | } 35 | //标记当前的readIndex的位置 36 | in.markReaderIndex(); 37 | //读取传送过来的消息的长度。ByteBuf 的readInt()方法会让他的readIndex增加4。指针会向前移动4 38 | int dataLength = in.readInt(); 39 | if (in.readableBytes() < dataLength) { 40 | //到的消息体长度如果小于我们传送过来的消息长度,则resetReaderIndex. 41 | // 这个配合markReaderIndex使用的。把readIndex重置到mark的地方 42 | in.resetReaderIndex(); 43 | return; 44 | } 45 | byte[] data = new byte[dataLength]; 46 | in.readBytes(data); 47 | //反序列化 48 | Object obj = FstSerializer.deserialize(data, genericClass); 49 | out.add(obj); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/src/main/java/com/uifuture/unpack/protocol/TinyEncoder.java: -------------------------------------------------------------------------------- 1 | package com.uifuture.unpack.protocol; 2 | 3 | import com.uifuture.unpack.codec.FstSerializer; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandler; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.MessageToByteEncoder; 8 | 9 | /** 10 | * Encoder 11 | */ 12 | @ChannelHandler.Sharable 13 | public class TinyEncoder extends MessageToByteEncoder { 14 | private Class genericClass; 15 | 16 | public TinyEncoder(Class genericClass) { 17 | this.genericClass = genericClass; 18 | } 19 | 20 | /** 21 | * 编码 22 | * 23 | * @param ctx 24 | * @param in 25 | * @param out 26 | * @throws Exception 27 | */ 28 | @Override 29 | public void encode(ChannelHandlerContext ctx, Object in, ByteBuf out) { 30 | //判断解码类型 31 | if (genericClass.isInstance(in)) { 32 | //序列化 33 | byte[] data = FstSerializer.serialize(in); 34 | //设置消息头为长度。消息头类型为int 35 | out.writeInt(data.length); 36 | //消息体 37 | out.writeBytes(data); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/src/main/java/com/uifuture/unpack/server/Server.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.unpack.server; 6 | 7 | import com.uifuture.unpack.protocol.Request; 8 | import com.uifuture.unpack.protocol.Response; 9 | import com.uifuture.unpack.protocol.TinyDecoder; 10 | import com.uifuture.unpack.protocol.TinyEncoder; 11 | import io.netty.bootstrap.ServerBootstrap; 12 | import io.netty.channel.ChannelFuture; 13 | import io.netty.channel.ChannelInitializer; 14 | import io.netty.channel.ChannelOption; 15 | import io.netty.channel.nio.NioEventLoopGroup; 16 | import io.netty.channel.socket.SocketChannel; 17 | import io.netty.channel.socket.nio.NioServerSocketChannel; 18 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 19 | 20 | /** 21 | * @author chenhx 22 | * @version Server.java, v 0.1 2018-08-08 下午 2:51 23 | */ 24 | public class Server { 25 | 26 | private final int port; 27 | 28 | public Server(int port) { 29 | this.port = port; 30 | } 31 | 32 | public static void main(String[] args) throws Exception { 33 | int port = 8081; 34 | new Server(port).start(); 35 | } 36 | 37 | public void start() throws Exception { 38 | NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); 39 | NioEventLoopGroup workerGroup = new NioEventLoopGroup(); 40 | try { 41 | ServerBootstrap b = new ServerBootstrap(); 42 | b.group(bossGroup, workerGroup) 43 | .channel(NioServerSocketChannel.class) 44 | .childHandler(new ChannelInitializer() { 45 | @Override 46 | public void initChannel(SocketChannel ch) { 47 | ch.pipeline() 48 | .addLast(new LengthFieldBasedFrameDecoder(1024 * 1024, 0, 4, 0, 0)) 49 | // 添加编解码. 发送自定义的类型, 而Handler的方法接收的msg参数的实际类型也是相应的自定义类了 50 | .addLast(new TinyDecoder(Request.class)) 51 | .addLast(new TinyEncoder(Response.class)) 52 | .addLast(new ServerHandler()); 53 | } 54 | }) 55 | .option(ChannelOption.SO_BACKLOG, 128) 56 | .childOption(ChannelOption.SO_KEEPALIVE, true); 57 | ChannelFuture f = b.bind(port).sync(); 58 | System.out.println(Server.class.getName() + " started and listen on " + f.channel().localAddress()); 59 | f.channel().closeFuture().sync(); 60 | } finally { 61 | //释放 channel 和 块,直到它被关闭 62 | bossGroup.shutdownGracefully(); 63 | workerGroup.shutdownGracefully(); 64 | } 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /netty-not-sticky-pack-demo/src/main/java/com/uifuture/unpack/server/ServerHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.unpack.server; 6 | 7 | import com.uifuture.unpack.model.User; 8 | import com.uifuture.unpack.protocol.Request; 9 | import com.uifuture.unpack.protocol.Response; 10 | import io.netty.channel.ChannelFutureListener; 11 | import io.netty.channel.ChannelHandlerContext; 12 | import io.netty.channel.SimpleChannelInboundHandler; 13 | 14 | /** 15 | * @author chenhx 16 | * @version ServerHandler.java, v 0.1 2018-08-08 下午 2:52 17 | */ 18 | public class ServerHandler extends SimpleChannelInboundHandler { 19 | @Override 20 | protected void channelRead0(ChannelHandlerContext ctx, Request request) throws Exception { 21 | System.out.println("服务端接收到的消息 : " + request); 22 | Response response = new Response(); 23 | response.setRequestId(2L); 24 | User user = new User(); 25 | user.setUsername("测试"); 26 | user.setPassword("1234"); 27 | user.setAge(21); 28 | response.setResult(user); 29 | //addListener是非阻塞的,异步执行。它会把特定的ChannelFutureListener添加到ChannelFuture中,然后I/O线程会在I/O操作相关的future完成的时候通知监听器。 30 | ctx.writeAndFlush(response).addListener((ChannelFutureListener) channelFuture -> 31 | System.out.println("接口响应:" + request.getRequestId()) 32 | ); 33 | } 34 | } -------------------------------------------------------------------------------- /netty-serialization-demo/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenhaoxiang/netty-demo/f7de6be96b260efd200105687157d776601e94d4/netty-serialization-demo/README.md -------------------------------------------------------------------------------- /netty-serialization-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | netty-demo 7 | com.uifuture.netty 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | netty-serialization-demo 13 | 14 | 15 | 16 | de.ruedigermoeller 17 | fst 18 | 2.52 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /netty-serialization-demo/src/main/java/com/uifuture/client/Client.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.client; 6 | 7 | import com.uifuture.protocol.Request; 8 | import com.uifuture.protocol.Response; 9 | import com.uifuture.protocol.TinyDecoder; 10 | import com.uifuture.protocol.TinyEncoder; 11 | import io.netty.bootstrap.Bootstrap; 12 | import io.netty.channel.ChannelFuture; 13 | import io.netty.channel.ChannelInitializer; 14 | import io.netty.channel.EventLoopGroup; 15 | import io.netty.channel.nio.NioEventLoopGroup; 16 | import io.netty.channel.socket.SocketChannel; 17 | import io.netty.channel.socket.nio.NioSocketChannel; 18 | 19 | import java.net.InetSocketAddress; 20 | 21 | /** 22 | * @author chenhx 23 | * @version Client.java, v 0.1 2018-08-08 下午 3:07 24 | */ 25 | public class Client { 26 | private final String host; 27 | private final int port; 28 | 29 | public Client(String host, int port) { 30 | this.host = host; 31 | this.port = port; 32 | } 33 | 34 | public static void main(String[] args) throws Exception { 35 | final String host = "127.0.0.1"; 36 | final int port = 8081; 37 | 38 | new Client(host, port).start(); 39 | } 40 | 41 | public void start() throws Exception { 42 | EventLoopGroup group = new NioEventLoopGroup(); 43 | try { 44 | Bootstrap b = new Bootstrap(); 45 | b.group(group) 46 | .channel(NioSocketChannel.class) 47 | .remoteAddress(new InetSocketAddress(host, port)) 48 | .handler(new ChannelInitializer() { 49 | @Override 50 | public void initChannel(SocketChannel ch) 51 | throws Exception { 52 | ch.pipeline() 53 | // 添加编解码. 发送自定义的类型, 而Handler的方法接收的msg参数的实际类型也是相应的自定义类了 54 | .addLast(new TinyEncoder(Request.class)) 55 | .addLast(new TinyDecoder(Response.class)) 56 | .addLast(new ClientHandler()); 57 | } 58 | }); 59 | 60 | ChannelFuture f = b.connect().sync(); 61 | f.channel().closeFuture().sync(); 62 | } finally { 63 | group.shutdownGracefully().sync(); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /netty-serialization-demo/src/main/java/com/uifuture/client/ClientHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.client; 6 | 7 | import com.uifuture.model.User; 8 | import com.uifuture.protocol.Request; 9 | import com.uifuture.protocol.Response; 10 | import io.netty.channel.ChannelHandlerContext; 11 | import io.netty.channel.SimpleChannelInboundHandler; 12 | 13 | /** 14 | * @author chenhx 15 | * @version ClientHandler.java, v 0.1 2018-08-08 下午 3:07 16 | */ 17 | public class ClientHandler extends SimpleChannelInboundHandler { 18 | 19 | /** 20 | * 通道注册 21 | * 22 | * @param ctx 23 | * @throws Exception 24 | */ 25 | @Override 26 | public void channelRegistered(ChannelHandlerContext ctx) throws Exception { 27 | super.channelRegistered(ctx); 28 | } 29 | 30 | /** 31 | * 服务器的连接被建立后调用 32 | * 建立连接后该 channelActive() 方法被调用一次 33 | * 34 | * @param ctx 35 | */ 36 | @Override 37 | public void channelActive(ChannelHandlerContext ctx) { 38 | Request request = new Request(); 39 | request.setRequestId(3L); 40 | User user = new User(); 41 | user.setUsername("测试客户端"); 42 | user.setPassword("4567"); 43 | user.setAge(21); 44 | request.setParameters(user); 45 | //当被通知该 channel 是活动的时候就发送信息 46 | ctx.writeAndFlush(request); 47 | } 48 | 49 | @Override 50 | protected void channelRead0(ChannelHandlerContext ctx, Response response) throws Exception { 51 | System.out.println("服务器发来消息 : " + response); 52 | } 53 | 54 | /** 55 | * 捕获异常时调用 56 | * 57 | * @param ctx 58 | * @param cause 59 | */ 60 | @Override 61 | public void exceptionCaught(ChannelHandlerContext ctx, 62 | Throwable cause) { 63 | //记录错误日志并关闭 channel 64 | cause.printStackTrace(); 65 | ctx.close(); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /netty-serialization-demo/src/main/java/com/uifuture/codec/FstSerializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.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-serialization-demo/src/main/java/com/uifuture/model/User.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.model; 6 | 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * 传输测试的实体类 13 | * 14 | * @author chenhx 15 | * @version User.java, v 0.1 2018-08-08 下午 3:14 16 | */ 17 | @Data 18 | public class User implements Serializable { 19 | private static final long serialVersionUID = -5135011481747489263L; 20 | private String username; 21 | private String password; 22 | private Integer age; 23 | } -------------------------------------------------------------------------------- /netty-serialization-demo/src/main/java/com/uifuture/protocol/Request.java: -------------------------------------------------------------------------------- 1 | package com.uifuture.protocol; 2 | 3 | 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * 请求数据 10 | */ 11 | @Data 12 | public class Request implements Serializable { 13 | private static final long serialVersionUID = -2747321595912488569L; 14 | private Long requestId; 15 | private Object parameters; 16 | } -------------------------------------------------------------------------------- /netty-serialization-demo/src/main/java/com/uifuture/protocol/Response.java: -------------------------------------------------------------------------------- 1 | package com.uifuture.protocol; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 响应数据 9 | */ 10 | @Data 11 | public class Response implements Serializable { 12 | private static final long serialVersionUID = -3136380221020337915L; 13 | private Long requestId; 14 | private String error; 15 | private Object result; 16 | } 17 | -------------------------------------------------------------------------------- /netty-serialization-demo/src/main/java/com/uifuture/protocol/TinyDecoder.java: -------------------------------------------------------------------------------- 1 | package com.uifuture.protocol; 2 | 3 | import com.uifuture.codec.FstSerializer; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.ByteToMessageDecoder; 7 | 8 | import java.util.List; 9 | 10 | public class TinyDecoder extends ByteToMessageDecoder { 11 | private Class genericClass; 12 | 13 | public TinyDecoder(Class genericClass) { 14 | this.genericClass = genericClass; 15 | } 16 | 17 | /** 18 | * 解码 19 | * 20 | * @param ctx 21 | * @param in 22 | * @param out 23 | */ 24 | @Override 25 | public final void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { 26 | int size = in.readableBytes(); 27 | byte[] data = new byte[size]; 28 | in.readBytes(data); 29 | Object obj = FstSerializer.deserialize(data, genericClass); 30 | out.add(obj); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /netty-serialization-demo/src/main/java/com/uifuture/protocol/TinyEncoder.java: -------------------------------------------------------------------------------- 1 | package com.uifuture.protocol; 2 | 3 | import com.uifuture.codec.FstSerializer; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandler; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.MessageToByteEncoder; 8 | 9 | /** 10 | * Encoder 11 | */ 12 | @ChannelHandler.Sharable 13 | public class TinyEncoder extends MessageToByteEncoder { 14 | private Class genericClass; 15 | 16 | public TinyEncoder(Class genericClass) { 17 | this.genericClass = genericClass; 18 | } 19 | 20 | /** 21 | * 编码 22 | * @param ctx 23 | * @param in 24 | * @param out 25 | * @throws Exception 26 | */ 27 | @Override 28 | public void encode(ChannelHandlerContext ctx, Object in, ByteBuf out) { 29 | if (genericClass.isInstance(in)) { 30 | byte[] data = FstSerializer.serialize(in); 31 | out.writeBytes(data); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /netty-serialization-demo/src/main/java/com/uifuture/server/Server.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.server; 6 | 7 | import com.uifuture.protocol.Request; 8 | import com.uifuture.protocol.Response; 9 | import com.uifuture.protocol.TinyDecoder; 10 | import com.uifuture.protocol.TinyEncoder; 11 | import io.netty.bootstrap.ServerBootstrap; 12 | import io.netty.channel.ChannelFuture; 13 | import io.netty.channel.ChannelInitializer; 14 | import io.netty.channel.ChannelOption; 15 | import io.netty.channel.nio.NioEventLoopGroup; 16 | import io.netty.channel.socket.SocketChannel; 17 | import io.netty.channel.socket.nio.NioServerSocketChannel; 18 | 19 | /** 20 | * @author chenhx 21 | * @version Server.java, v 0.1 2018-08-08 下午 2:51 22 | */ 23 | public class Server { 24 | 25 | private final int port; 26 | 27 | public Server(int port) { 28 | this.port = port; 29 | } 30 | 31 | public static void main(String[] args) throws Exception { 32 | int port = 8081; 33 | new Server(port).start(); 34 | } 35 | 36 | public void start() throws Exception { 37 | NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); 38 | NioEventLoopGroup workerGroup = new NioEventLoopGroup(); 39 | try { 40 | ServerBootstrap b = new ServerBootstrap(); 41 | b.group(bossGroup, workerGroup) 42 | .channel(NioServerSocketChannel.class) 43 | .childHandler(new ChannelInitializer() { 44 | @Override 45 | public void initChannel(SocketChannel ch) { 46 | ch.pipeline() 47 | // 添加编解码. 发送自定义的类型, 而Handler的方法接收的msg参数的实际类型也是相应的自定义类了 48 | .addLast(new TinyDecoder(Request.class)) 49 | .addLast(new TinyEncoder(Response.class)) 50 | .addLast(new ServerHandler()); 51 | } 52 | }) 53 | .option(ChannelOption.SO_BACKLOG, 128) 54 | .childOption(ChannelOption.SO_KEEPALIVE, true); 55 | ChannelFuture f = b.bind(port).sync(); 56 | System.out.println(Server.class.getName() + " started and listen on " + f.channel().localAddress()); 57 | f.channel().closeFuture().sync(); 58 | } finally { 59 | //释放 channel 和 块,直到它被关闭 60 | bossGroup.shutdownGracefully(); 61 | workerGroup.shutdownGracefully(); 62 | } 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /netty-serialization-demo/src/main/java/com/uifuture/server/ServerHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * uifuture.com 3 | * Copyright (C) 2013-2018 All Rights Reserved. 4 | */ 5 | package com.uifuture.server; 6 | 7 | import com.uifuture.model.User; 8 | import com.uifuture.protocol.Request; 9 | import com.uifuture.protocol.Response; 10 | import io.netty.channel.ChannelFutureListener; 11 | import io.netty.channel.ChannelHandlerContext; 12 | import io.netty.channel.SimpleChannelInboundHandler; 13 | 14 | /** 15 | * @author chenhx 16 | * @version ServerHandler.java, v 0.1 2018-08-08 下午 2:52 17 | */ 18 | public class ServerHandler extends SimpleChannelInboundHandler { 19 | @Override 20 | protected void channelRead0(ChannelHandlerContext ctx, Request request) throws Exception { 21 | System.out.println("服务端接收到的消息 : " + request); 22 | Response response = new Response(); 23 | response.setRequestId(2L); 24 | response.setError("success"); 25 | User user = new User(); 26 | user.setUsername("测试"); 27 | user.setPassword("1234"); 28 | user.setAge(21); 29 | response.setResult(user); 30 | //addListener是非阻塞的,异步执行。它会把特定的ChannelFutureListener添加到ChannelFuture中,然后I/O线程会在I/O操作相关的future完成的时候通知监听器。 31 | ctx.writeAndFlush(response).addListener((ChannelFutureListener) channelFuture -> 32 | System.out.println("接口响应:" + request.getRequestId()) 33 | ); 34 | } 35 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.uifuture.netty 8 | netty-demo 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | netty-serialization-demo 13 | netty-introduction-demo 14 | netty-heartbeat-detection-demo 15 | netty-not-sticky-pack-demo 16 | 17 | 18 | 19 | 21 | 22 | io.netty 23 | netty-all 24 | 4.1.25.Final 25 | 26 | 27 | 28 | org.projectlombok 29 | lombok 30 | 1.16.22 31 | 32 | 33 | 34 | 35 | --------------------------------------------------------------------------------