netty 心跳

服务端:
public class NettySer {
	public static void main(String[] args) {
		NettySer ns = new NettySer();
		ns.start();
	}

	private void start() {
		NioEventLoopGroup boss = new NioEventLoopGroup(1);
		NioEventLoopGroup worker = new NioEventLoopGroup();// 默认为cpu数乘2

		try {
			ServerBootstrap sb = new ServerBootstrap();
			// 设置服务端ServerBootStrap启动参数
			sb.group(boss, worker);
			sb.channel(NioServerSocketChannel.class); // 我要指定使用NioServerSocketChannel这种类型的通道
			sb.option(ChannelOption.SO_BACKLOG, 1024);// 设置tcp缓冲区, 支持多少个客户端连接
			sb.childHandler(new ChannelInitializer<Channel>() {// 一定要使用 childHandler 去绑定具体的事件处理器

				@Override
				protected void initChannel(Channel ch) throws Exception {
					ch.pipeline().addLast(new ObjectEncoder());
					ch.pipeline().addLast(new ObjectDecoder(1024 * 1024 * 1024,
							ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader())));
					ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {

						// key是ip, value是认证码
						private HashMap<String, String> AUTH_IP_MAP = new HashMap<>();
						// 成功链接标志
						private final String SUCCESS_KEY = "auth_success_key";

						// 模拟认证码(一个客户端一个), 实际开发中存在数据库里
						{
							AUTH_IP_MAP.put("10.10.10.22", "1234");
						}

						/**
						 * 安全认证
						 */
						private boolean auth(ChannelHandlerContext ctx, Object msg) {
							String[] ret = ((String) msg).split(",");
							String auth = AUTH_IP_MAP.get(ret[0]);
							if (auth != null && auth.equals(ret[1])) {
								ctx.writeAndFlush(SUCCESS_KEY);
								return true;
							} else {
								ctx.writeAndFlush("auth failure !").addListener(ChannelFutureListener.CLOSE);
								return false;
							}
						}

						@Override
						public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
							if (msg instanceof String) { // 第一次连接要进行安全认证
								System.out.println("收到 string msg=" + msg);
								auth(ctx, msg);
							} else if (msg instanceof RequestInfo) {// 心跳包
								System.out.println("收到 RequestInfo msg=" + msg);
								RequestInfo info = (RequestInfo) msg;
								System.out.println("--------------------------------------------");
								System.out.println("当前主机ip为: " + info.getIp());
								System.out.println("当前主机cpu情况: ");
								HashMap<String, Object> cpu = info.getCpuPercMap();
								System.out.println("总使用率: " + cpu.get("combined"));

								System.out.println("当前主机memory情况: ");
								HashMap<String, Object> memory = info.getMemoryMap();
								System.out.println("内存总量: " + memory.get("total"));
								System.out.println("--------------------------------------------");

								ctx.writeAndFlush("info received!");
							} else {
								ctx.writeAndFlush("connect failure!").addListener(ChannelFutureListener.CLOSE);
							}
						}

						@Override
						public void channelActive(ChannelHandlerContext ctx) throws Exception {
							System.out.println("client active");
							super.channelActive(ctx);
						}

					});
				}
			});

			// 绑定指定的端口进行监听
			ChannelFuture f = sb.bind(9090).sync();
			// 等待服务端监听端口关闭
			f.channel().closeFuture().sync();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			boss.shutdownGracefully();
			worker.shutdownGracefully();
		}
	}
}
客户端:
public class NettyCli {
	public static void main(String[] args) {
		NioEventLoopGroup worker = new NioEventLoopGroup();// 默认为cpu数乘2
		try {
			Bootstrap b = new Bootstrap();
			b.group(worker);
			b.channel(NioSocketChannel.class);
			b.handler(new ChannelInitializer() {

				// @Override
				protected void initChannel(Channel ch) throws Exception {
					ch.pipeline().addLast(new ObjectEncoder());
					ch.pipeline().addLast(new ObjectDecoder(1024 * 1024 * 1024,
							ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader())));
					ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {

						// 定时任务
						private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
						private ScheduledFuture<?> heartBeat;
						// 本机ip地址
						private InetAddress addr;
						private static final String SUCCESS_KEY = "auth_success_key";
						// 密码
						private String key = "1234";

						/**
						 * 第一次连接要进行安全认证, 发送认证信息要服务器 此方法在第一次和服务端链接时调用,服务端会在read方法里收到msg
						 */
						@Override
						public void channelActive(ChannelHandlerContext ctx) throws Exception {
							System.out.println("ser active");
							addr = InetAddress.getLocalHost();
							String ip = addr.getHostAddress();
							// 认证信息
							String auth = ip + "," + key;
							ctx.writeAndFlush(auth);
							super.channelActive(ctx);
						}

						@Override
						public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
							try {
								if (msg instanceof String) { // 收到服务端消息,已建立连接
									String ret = (String) msg;
									System.out.println("cli channelRead msg = " + msg);
									if (SUCCESS_KEY.equals(ret)) {// 认证成功,开始发心跳
										// 定时发送心跳消息
										System.out.println("定时发送心跳消息..");
										this.heartBeat = this.scheduler.scheduleWithFixedDelay(new HeartBeatTask(ctx),
												0, 2, TimeUnit.SECONDS);
									} else if ("info received!".equals(ret)){// 收到服务端心跳回复
										System.out.println("收到心跳");
									}else {//认证失败
										System.out.println("收到心跳");
									}
								}
							} finally {
								ReferenceCountUtil.release(msg);
							}
						}

						/**
						 * 心跳信息类
						 */
						class HeartBeatTask implements Runnable {
							private final ChannelHandlerContext ctx;

							public HeartBeatTask(final ChannelHandlerContext ctx) {
								this.ctx = ctx;
							}

							@Override
							public void run() {
								try {
									RequestInfo info = new RequestInfo();
									/*
									 * 组装 info
									 */
									// ip
									info.setIp(addr.getHostAddress());
									// cpu prec
									HashMap<String, Object> cpuPercMap = new HashMap<>();
									cpuPercMap.put("combined", "jww");
									// memory
									HashMap<String, Object> memoryMap = new HashMap<>();
									memoryMap.put("total", "jww");
									info.setCpuPercMap(cpuPercMap);
									info.setMemoryMap(memoryMap);

									ctx.writeAndFlush(info);
								} catch (Exception e) {
									e.printStackTrace();
								}
							}
						}
					});

				}
			});

			// 连接Server
			final ChannelFuture future = b.connect("127.0.0.1", 9090).sync();

			// 等待连接关闭
			future.channel().closeFuture().sync();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			worker.shutdownGracefully();
		}

	}
}
心跳类:
public class RequestInfo implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private String ip ;
    private HashMap<String, Object> cpuPercMap ; //cpu状态
    private HashMap<String, Object> memoryMap; //内存状态
    //... other field

    public String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }
    public HashMap<String, Object> getCpuPercMap() {
        return cpuPercMap;
    }
    public void setCpuPercMap(HashMap<String, Object> cpuPercMap) {
        this.cpuPercMap = cpuPercMap;
    }
    public HashMap<String, Object> getMemoryMap() {
        return memoryMap;
    }
    public void setMemoryMap(HashMap<String, Object> memoryMap) {
        this.memoryMap = memoryMap;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值