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

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 block
							e.printStackTrace();
						}
					}
				}).start();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.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();// 开启channel
		
		ServerSocket 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>(){
	
				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					// TODO Auto-generated method stub
					ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
						
						@Override
						public 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 block
			e.printStackTrace();
		} finally {
			try {
				group.shutdownGracefully().sync();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.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>(){

				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					// TODO Auto-generated method stub
					ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
						// 处理客户端发来的信息
						@Override
						public void channelRead(ChannelHandlerContext ctx , Object msg){
							
						}
						@Override
						public 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值