Netty实战读书笔记(第四章)

来源:互联网 发布:在淘宝上怎样发链接 编辑:程序博客网 时间:2024/05/21 12:41

Netty实战第四章:传输

比较java自带的OIO、NIO、Netty提供的OIO、Netty提供的NIO。

OIO:

import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class PlainOioServer {final int port = 8888;public void server() throws IOException{// 绑定端口final ServerSocket server = new ServerSocket(this.port);try {while(true){// 阻塞接受请求final Socket socket = server.accept();// 开启新线程处理请求。new Thread(new Runnable(){public void run(){try {InputStream input = socket.getInputStream();OutputStream output = socket.getOutputStream();output.write("ok".getBytes());output.flush();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}).start();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally{server.close();}}}
NIO

import java.io.IOException;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.util.Iterator;import java.util.Set;public class PlainNioServer {private int port = 8888;public void server() throws IOException{final ServerSocketChannel channel = ServerSocketChannel.open();// 开启channelServerSocket serverSocket = channel.socket();serverSocket.bind(new InetSocketAddress(this.port));// 将serverSocket绑定到指定端口。Selector select = Selector.open();// 打开selector,将channel注册到selector中。channel.register(select, SelectionKey.OP_ACCEPT); // selector注册为可接收请求。final ByteBuffer msg = ByteBuffer.wrap("ok".getBytes());while(true){select.select();// 阻塞直到新的事件到达。Set<SelectionKey> keys = select.selectedKeys();// 获取所有事件的keys。Iterator<SelectionKey> it = keys.iterator();while(it.hasNext()){SelectionKey key = it.next();if (key.isAcceptable()){} if (key.isWritable()){}}}}}

Netty自带的OIO:

import java.net.InetSocketAddress;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;import io.netty.channel.ChannelInitializer;import io.netty.channel.EventLoopGroup;import io.netty.channel.oio.OioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.oio.OioServerSocketChannel;public class NettyOioServer {private int port ;public NettyOioServer(int port ){this.port = port;}public void server(){EventLoopGroup group = new OioEventLoopGroup();// 创建阻塞型io。try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(group).channel(OioServerSocketChannel.class)// IO类型不同,指定socketchannel为阻塞类型。.localAddress(new InetSocketAddress(this.port))// 将server绑定到指定端口上.childHandler(new ChannelInitializer<SocketChannel>(){@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// TODO Auto-generated method stubch.pipeline().addLast(new ChannelInboundHandlerAdapter(){@Overridepublic void channelRead(ChannelHandlerContext ct , Object msg){}@Override  public void channelReadComplete(ChannelHandlerContext ct ){}});}});ChannelFuture future = bootstrap.bind().sync();// 应该是现有bootstrap执行bind到channelFuture上future.channel().closeFuture().sync();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {try {group.shutdownGracefully().sync();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

Netty自带的NIO:

import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;import io.netty.channel.ChannelInitializer;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;public class NettyNioServer {private int port ;public NettyNioServer(int port ){this.port = port;}public void server() throws InterruptedException{EventLoopGroup group = new NioEventLoopGroup();try{ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(group).channel(NioServerSocketChannel.class)// 申明了IO类型.localAddress(new InetSocketAddress(this.port))//绑定了端口号.childHandler(new ChannelInitializer<SocketChannel>(){@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// TODO Auto-generated method stubch.pipeline().addLast(new ChannelInboundHandlerAdapter(){// 处理客户端发来的信息@Overridepublic void channelRead(ChannelHandlerContext ctx , Object msg){}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx){}});}});// 将启动器绑定到channelFuture 上,同步阻塞绑定。ChannelFuture future = bootstrap.bind().sync();// 获取channel,在执行完毕后关闭,同步阻塞关闭。future.channel().closeFuture().sync();} finally{group.shutdownGracefully().sync();}}}

java JDK自带的OIO和NIO属于不同的编程模式,Netty通过统一的编程规范,把NIO和OIO统一为相识的编程模式。

传输API:


每个channel都会被分配一个channelPipeLine和channelConfig,channelPipeline相当于channelHandler容器,通过将channelHandler add到pipeline中,管理channelHandler,形成适配器方式的管理, channelPipeline不仅包含处理事件,还包含需要处理的入站和出站的数据。

ChannelHandler处理的常规事件:

1 , 将数据从一种格式转换为另一种格式。比如decode、encode。

2 , 提供异常的通知。比如exceptionCaught。

3 , 提供给用户事件通知消息。

4 , 当channel注册到EventLoop或者从EventLoop注销时的通知。

channelPipeLine可以动态的向Pipeline中添加channelHandler,例如当需要支持STRATTLS协议时,可以向PIpeline中添加对应的handler,也实现了拦截器模式。

channel支持多线程操作,在多线程下也是安全的。

Netty数据传输:

Netty提供几种数据传输方法,不同的数据传输方式支持的协议不同,主要的数据传输方式:

1 , NIO,基于java NIO的数据传输方式,使用selector注册的方式。


2 , epoll,由JNI提供的epoll()支持。

Netty为linux提供的一组基于JNI的epoll()方法的NIO,如果应用程序在linux中运行,性能好于java自带的NIO。

3 , local,在VM内部传输数据。

提供了在同一个JVM中运行的客户端和服务器异步通信的API,在channel启动的时候就注册了,没有网络流量的交互,不能与其他方式交换数据。

4, OIO的方式。

阻塞的方式。


5 , embedding的方式。



阅读全文
0 0
原创粉丝点击