Netty(3):核心部件:Transport 传输

版权声明:转载随意,附上转载信息即可 :) https://blog.csdn.net/Al_assad/article/details/79451899

Netty 核心部件:Transport 传输功能


JDK 中对于 NIO(java.nio)、OIO(java.net) 的网络编程 API 的差异很大,在进行程序移植时的难度比较大,而 Netty 对于 NIO、OIO 等提供了统一的 API 接口;
如对于 01. Netty 主要部件介绍 & Hello World 实例 中的 Hello World 实例,使用 NIO Channel 作为实现,假如要更换为 OIO Channel 实现,只需要做出很少量的该改动,如下:
EchoServer
 
......
ServerBootstrap bootstrap = new ServerBootstrap();             
bootstrap.group(workerGroup)                                    
        .channel(OioServerSocketChannel.class)           //使用 OIO ServerSocket 传输通道
        .localAddress(new InetSocketAddress((port)))            
......
EchoClient
 
.....
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workerGroup)
        .channel(OioSocketChannel.class)     //使用 OIO Socket 传输通道
        .remoteAddress(new InetSocketAddress(host,port))
.....



Netty 支持的传输方式


NIO
io.netty.channel.socket.nio 包提供支持,基于 java.nio.channels 包,使用选择器作为基础实现,默认实现有如下:
    • NioServerSocketChannel:用于 TCP 协议的服务端;
    • NioSocketChannel:用于 TCP 协议的客户端;
    • NioDatagramChannel:用于 UDP 协议;
Non Blocking I/O 是最常用的方式,通过选择器提供了完全异步的方式操作所有的 I/O ;
NIO 方式通常用在高连接数的场景下;

OIO
io.netty.channel.socket.oio 包提供支持,基于 java.net 包,使用阻塞流作为基础实现,默认的实现如下:
    • OioServerSocketChannel:用于 TCP 协议的服务端;
    • OioSocketChannel:用于 TCP 协议的客户端;
    • OioDatagramChannel:用于 UDP 协议;
Old Blocking I/O 即阻塞 IO 操作,为面向流的 IO 操作,基于阻塞流为基础实现的同步流操作方式,虽然是旧式的 IO 方案,但是还是有一定的使用场景;
OIO 方式通常使用在需要阻塞 IO 、需要低延迟的使用场景,同时该场景为低连接数的;

Local
io.netty.channel.local 包提供支持,默认实现为 LocalChannel ;
Local 本地传输方式用于在 JVM 虚拟机之间进行本地通信;

Embedded
由  io.netty.channel.embedded 包提供支持,默认实现为 EmbeddedChannel;
Embedded 嵌入传输允许嵌入到一个 ChannelHandler 到另一个 ChannelHandler 的传输;
Embedded 方式通常用于测试 ChannelHandler 的实现;




Netty 用于传输的 API


Netty Transport API 的核心为 Channel 接口,由于进行所有进出站操作,如下:

每一个 Channel 都会分配一个 ChannelPipeline 和 ChannelConfig,前者为容纳 ChannelHandler 链的容器,后者负责设置为储存 Channel 的配置,并允许在运行期更改这些配置;

ChannelHandler 负责进行出站、入站的具体逻辑处理操作,可以在运行期根据需要添加 ChannelHandler 实例到 ChannelPipeline,或者从 ChannelPipeline 删除相应的 ChannelHandler 实现高度灵活的 Netty 程序;

Channel 本身提供了很多方法,主要如下:
eventLoop() 返回分配给 Channel 的 EventLoop
pipeline() 返回分配给 Channel 的 ChannelPipeline
isActive() 返回 Channel 是否激活,已激活说明与远程连接对等
localAddress() 返回已绑定的本地 SocketAddress
remoteAddress() 返回已绑定的远程 SocketAddress
write() 写数据到远程客户端,数据通过 ChannelPipeline 传输过去
flush() 刷新先前的数据
writeAndFlush() 一个方便的方法用户调用 write()而后调用 flush()

如以下实例,演示写数据到远程客户端:
 
Channel channel = ...;            // 获取channel的引用
ByteBuf buf = Unpooled.copiedBuffer("Hello Wrold!", CharsetUtil.UTF_8);      
ChannelFuture cf = channel.writeAndFlush(buf);           //写入缓冲区数据到 Channel,并刷新缓冲区
cf.addListener(new ChannelFutureListener() {           //添加 ChannelFuture 监听器,获取在IO操作完成后的通知
    @Override
    public void operationComplete(ChannelFuture future) {
        if (future.isSuccess()) {                
            System.out.println("Write successful");
        } else {
            System.err.println("Write error");    
            future.cause().printStackTrace();
        }
    }
});

Netty 的 Channel 本身是线程安全区的,可以被多个不同的线程同时操作,以下是一个实例:
 
final Channel channel = ...;                     // 获取channel的引用
final ByteBuf buf = Unpooled.copiedBuffer("Hello World!",CharsetUtil.UTF_8).retain();   
Runnable writer = new Runnable() {               
    @Override
    public void run() {
        channel.writeAndFlush(buf.duplicate());
    }
};
Executor executor = Executors.newCachedThreadPool();
executor.execute(writer);         //将 Channel 写进一个线程
executor.execute(writer);         //将 Channel 写进另一个线程



猜你喜欢

转载自blog.csdn.net/Al_assad/article/details/79451899