1、netty5和netty4的区别不是很大,但是与netty3差别还是有的。这里不介绍netty4,因为和netty5的方式都差不多。netty5的复杂性相对于netty3要多很多了。基本上架构都被重构了。所以这里主要是介绍一些属性和用法。

  2、核心的变化主要有:

  支持Android
 
  提供了:
  • 移动设备变成更加强大
  • 通过Ice Cream Sandwich解决了在ADK中最著名的与NIO和SSLEngine相关的问题,且
  • 用户显然想要重用他们应用中的的编解码和处理器代码。
  我们决定官方支持Android(4.0及以上版本)
 
  简化处理器层次
 
  ChannelInboundHandler和ChannelOutboundHandler整合为ChannelHandler。ChannelHandler现在包含输入和输出的处理方法。
 
  ChannelInboundHandlerAdapter,ChannelOutboundHandlerAdapter和ChannelDuplexHandlerAdapter已被废弃,由 ChannelHandlerAdapter代替。
 
  由于现在无法区分处理器(handler) 是输入还是输出的处理器,CombinedChannelDuplexHandler现在由 ChannelHandlerAppender代替。
 
  更多相关变化,可参考https://github.com/netty/netty/pull/1999
 
  channelRead0() → messageReceived()
 
  我知道。这是一个愚蠢的错误。如果你使用了SimpleChannelInboundHandler,你需要把channelRead0()重命名为messageReceived()。
 
  废弃中移除的
 
  Channel.deregister()已被移除。不再生效和被使用。取而代之的,我们将允许Channel被充注册到不同的事件循环。
 
  ChannelHandlerContext.attr(..) == Channel.attr(..)
 
  Channel和ChannelHandlerContext类都实现了AttributeMap接口,使用户可以在其上关联一个或多个属性。有时会让用户感到困惑的是Channel和ChannelHandlerContext都有其自己的存储用户定义属性的容器。例如,即使你通过Channel.attr(KEY_X).set(valueX)给属性'KEY_X’赋值,你却无法通过ChannelHandlerContext.attr(KEY_X).get()方法获取到值。反之亦是如此。这种行为不仅仅令人不解而且还浪费内存。
 
  为了解决这个问题,我们决定每个Channel内部仅保留一个map。AttributeMap总是用AttributeKey作为它的key。AttributeKey确保键的唯一性,因此每个Channel中如果存在一个以上的属性容易是多余的。只要用户把他自己的AttributeKey定义成ChannelHandler的private static final变量,就不会有出现重复key的风险。
 
  更简单更精确的缓冲区泄漏追踪
 
 
  之前,查找缓冲区泄漏是很困难的,并且泄漏的警告信息也不是很有帮助。现在我们有了增强的泄漏报告机制,该机制会在增长超过上限时触发。
 
  更多的信息可查看:http://netty.io/wiki/reference-counted-objects.html 。由于该特性十分重要,所以也移植入了4..0.14.Final版中。
 
  PooledByteBufAllocator成为默认的allocator
 
  在4.x版本中,UnpooledByteBufAllocator是默认的allocator,尽管其存在某些限制。现在PooledByteBufAllocator已经广泛使用一段时间,并且我们有了增强的缓冲区泄漏追踪机制,所以是时候让PooledByteBufAllocator成为默认了。
 
  全局唯一的Channel ID
  每个Channel现在有了全局唯一的ID,其生成的依据是:
 
   * MAC地址(EUI-48或是EUI-64),最好是全局唯一的,
   * 当前进程的ID
   * System#currentTimeMillis()
   * System#nanoTime()
   * 随机的32位整数,以及
   * 系列递增的32位整数
 
  可通过Channel.id()方法获取Channel的ID。
 
  更灵活的线程模型
 
 
  增加了新的ChannelHandlerInvoker接口,用于使用户可以选择使用哪个线程调用事件处理方法。替代之前的在向ChannelPipeline添加 ChannelHandler时指定一个EventExecutor的方式,使用该特性需要指定一个用户自定义的 ChannelHandlerInvoker实现。
 
 
  EmbeddedChannel的易用性
 
  EmbeddedChannel中的readInbound()和readOutbound()方法返回专门类型的参数,因此你不必在转换他们的返回值。这可以简化你的测试用例代码。
EmbeddedChannel ch = ...;

// BEFORE:
FullHttpRequest req = (FullHttpRequest) ch.readInbound(); // AFTER:
FullHttpRequest req = ch.readInbound();
 
  使用Executor代替ThreadFactory
 
  有些应用要求用户使用Executor运行他们的任务。4.x版本要求用户在创建事件循环(event loop)时指定ThreadFacotry,现在不再是这样了。
 
  关于该变化的更多信息,可参考:https://github.com/netty/netty/pull/1762
 
  Class loader友好化
 
  一些类型,如AttributeKey对于在容器环境下运行的应用是不友好的,现在不是了。
 
  编解码和处理器(handlers)
 
   * XmlFrameDecoder支持流式的XML文档
 
   * 二进制的memcache协议编解码
   * 支持SPDY/3.1 (也移植到了4.x版本)
   * 重构了HTTP多部分的编解码
 

  3、这里写了一个简单的实现过程,来区分netty5和netty3的写法

  1)服务类和处理类

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder; public class Server { public static void main(String[] args) {
//服务类
ServerBootstrap serverBootstrap = new ServerBootstrap();
//声明两个线程池
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup(); try {
//设置线程组
serverBootstrap.group(boss,work);
//设置服务socket工厂
serverBootstrap.channel(NioServerSocketChannel.class);
//设置管道
serverBootstrap.childHandler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast(new StringDecoder());
channel.pipeline().addLast(new StringEncoder());
channel.pipeline().addLast(new ServerHandler());
}
});
//设置服务器连接数
serverBootstrap.option(ChannelOption.SO_BACKLOG,2048);
//设置tcp延迟状态
serverBootstrap.option(ChannelOption.TCP_NODELAY,true);
//设置激活状态,2小时清除
serverBootstrap.option(ChannelOption.SO_KEEPALIVE,true);
//监听端口
ChannelFuture channelFuture = serverBootstrap.bind(9000);
//等待服务器关闭
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭线程池
boss.shutdownGracefully();
work.shutdownGracefully();
} } }
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; public class ServerHandler extends SimpleChannelInboundHandler<String> { //接收消息并处理
protected void messageReceived(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
System.out.println(s);
channelHandlerContext.writeAndFlush("hello client");
}
}

  2)客户端和处理类

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder; import java.net.InetSocketAddress;
import java.util.Scanner; //单个客户端
public class Client { public static void main(String[] args) { //服务类
Bootstrap bootstrap = new Bootstrap();
//线程池
EventLoopGroup client = new NioEventLoopGroup(); try {
//设置线程组
bootstrap.group(client);
//设置socket工厂
bootstrap.channel(NioSocketChannel.class);
//设置管道处理
bootstrap.handler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast(new StringEncoder());
channel.pipeline().addLast(new StringDecoder());
channel.pipeline().addLast(new ClientHandler());
}
});
//连接服务器
ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress("localhost", 9000));
//输入信息测试
Scanner scanner = new Scanner(System.in);
while (true) {
String msg = scanner.nextLine();
channelFuture.channel().writeAndFlush(msg);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭线程池
client.shutdownGracefully();
}
}
}
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; public class ClientHandler extends SimpleChannelInboundHandler<String>{ //接收消息
protected void messageReceived(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
System.out.println(s);
}
}

  3)多个客户端

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder; import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicInteger; //多个客户端连接
public class MClient { //服务类
private Bootstrap bootstrap = new Bootstrap();
//因为线程组里面是线程安全的,所以这里采用数组的形式
private List<Channel> channels = new ArrayList<Channel>();
//原子类,用于计数
private AtomicInteger atomicInteger = new AtomicInteger();
//初始化操作
public void init(int count) {
//声明线程池
EventLoopGroup client = new NioEventLoopGroup();
//设置线程组
bootstrap.group(client);
//设置socket工厂
bootstrap.channel(NioSocketChannel.class);
//设置管道
bootstrap.handler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast(new StringEncoder());
channel.pipeline().addLast(new StringDecoder());
channel.pipeline().addLast(new ClientHandler());
}
});
//初始化连接
for (int i = 0; i < count; i++) {
ChannelFuture channelFuture = bootstrap.connect("10.0.20.154", 9000);
channels.add(channelFuture.channel());
}
} //获取下一个channel
public Channel nextChannel() {
return this.getChannel(0);
} private Channel getChannel(int n) {
//平均获取其中的channel
Channel channel = channels.get(Math.abs(atomicInteger.getAndIncrement() % channels.size()));
//判断是否连接
if (!channel.isActive()) {
//如果没有连接,选择激活替换
channels.set(channels.indexOf(channel), bootstrap.connect("10.0.20.154", 9000).channel());
//超出总长度,直接抛异常
if (n>=channels.size()) {
throw new RuntimeException("no use channel");
}
//递归,目的是获取下一个,直到数组没有channel
return getChannel(n+1);
}
return channel;
} public static void main(String[] args) {
MClient mClient = new MClient();
mClient.init(5);
Scanner scanner = new Scanner(System.in);
while (true) {
try {
String msg = scanner.nextLine();
mClient.nextChannel().writeAndFlush(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

nio之netty5应用的更多相关文章

  1. Netty、NIO、多线程

    一:Netty.NIO.多线程? 时隔很久终于又更新了!之前一直迟迟未动也是因为积累不够,后面比较难下手.过年期间@李林锋hw发布了一个Netty5.0架构剖析和源码解读,看完也是收获不少.前面的文章 ...

  2. 【转】Netty那点事(四)Netty与Reactor模式

    [原文]https://github.com/code4craft/netty-learning/blob/master/posts/ch4-reactor.md 一:Netty.NIO.多线程? 时 ...

  3. android netty5.0 编译时 java.lang.NoClassDefFoundError: io.netty.channel.nio.NioEventLoopGroup

    android netty5.0 编译时 java.lang.NoClassDefFoundError: io.netty.channel.nio.NioEventLoopGroup 复制netty包 ...

  4. Netty5序章之BIO NIO AIO演变

    Netty5序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使 ...

  5. 【原创】NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战

    概述 本文演示的是一个Android客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo. 当前由于NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能. ...

  6. 【原创】NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战

    前言 本文将演示一个iOS客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo.服务端将分别用MINA2和Netty4进行实现,而通信时服务端你只需选其一就行了.同 ...

  7. 【原创】NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示

    前言 NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能.这其中最流行的无非就是MINA和Netty了,MINA目前的主要版本是MINA2.而Netty的主要版本是Netty3和Netty ...

  8. 【原创】NIO框架入门(一):服务端基于Netty4的UDP双向通信Demo演示

    申明:本文由作者基于日常实践整理,希望对初次接触MINA.Netty的人有所启发.如需与作者交流,见文签名,互相学习. 学习交流 更多学习资料:点此进入 推荐 移动端即时通讯交流: 215891622 ...

  9. Netty5 + WebSocket 练习

    1. 了解WebSocket知识 略2. websocket实现系统简单反馈时间 WebSocketServerHandler.java package com.jieli.nettytest.web ...

随机推荐

  1. WAS缓存问题

    在项目中经常遇见这样的问题:修改应用的配置文件web.xml后,无论重启应用还是重启WebSphere服务器,都不能重新加载web.xml,导致修改的内容无效. 这个问题困扰了我好久,即使删除了${w ...

  2. Gluon 实现 dropout 丢弃法

    多层感知机中: hi 以 p 的概率被丢弃,以 1-p 的概率被拉伸,除以  1 - p import mxnet as mx import sys import os import time imp ...

  3. thinkphp 和 laravel使用sql语句操作db和源码浅析

    thinkphp 和 laravel是phper开发中用的比较多的两个框架,无所谓好坏,看个人习惯及喜爱! 前言对于一个PHP应用,可能最多的就是操作数据,以致于初学者有时只把php当做数据库增删查改 ...

  4. web.xml中Filter的作用

    Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码.做一些业务逻辑判断等.其工作原理是,只要你在web.xml文件配置好要 ...

  5. js 实现商品放大镜效果

    知识点,需熟悉下面属性及含义: offsetLeft           //获取元素相对左侧的距离 (计算是从最左侧边框外开始) offsetTop           //获取元素相对顶部的距离 ...

  6. C++实现的Buffer类

    写C#的同志一定觉得Byte []比C++的 BYTE * 加 Length的方式好的多.一来,只需要一个对象就可以是表示一段字节流,另一方面,由于C#的特性,不需要象C++那样还要记得删除指针.由于 ...

  7. python-常用模块之os、sys

    一.os os模块包含普遍的操作系统功能: os.pardir #获取当前目录的父目录字符串名:('..') os.makedirs('dirname1/dirname2') #可生成多层递归目录 o ...

  8. Relay GraphQL理解

    Relay是构建数据驱动 React 应用的js框架. Relay:特性一.声明式:不再使用一个命令式API与数据存储通讯.而是简单的使用RraphQL声明组件数据需求,让Relay理解如何及什么时候 ...

  9. C# abstract,virtual 修饰符

    abstract(抽象):该abstract修饰符指示要修改的东西有缺失或不完整的实现.abstract修饰符可以与类,方法,属性,索引器和事件一起使用.abstract在类声明中使用修饰符来指示类仅 ...

  10. IE下内容居中

    ie8下调了很长时间的居中问题,加一个body {text-align:center;},居然解决了.. 参考解决答案:*html * {margin:0px; padding:0;} 然后在盒子里b ...