Netty框架学习
Netty
Netty是一个异步的,基于事件模型驱动的网络应用框架。
1
| TCP/IP -> 原生JDK BIO -> NIO -> Netty
|
BIO - Blocking IO
- 类和接口都在 java.io 包中
- 同步并阻塞
- 一个连接一个线程
- 基于流的方式处理数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| package top.leezy.bio;
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
public class BIOServer { public static void main(String [] args) throws IOException {
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
ServerSocket serverSocket = new ServerSocket(15501);
System.out.println("Server start...");
while (true) { System.out.println("Main thread : ID: " + Thread.currentThread().getId() + " Name: " + Thread.currentThread().getName()); final Socket socket = serverSocket.accept(); System.out.println("connected a client"); newCachedThreadPool.execute(() -> { handler(socket); }); } }
public static void handler(Socket socket) { try { System.out.println("Handler Thread info: ID: " + Thread.currentThread().getId() + " Name: " + Thread.currentThread().getName()); byte[] bytes = new byte[1024]; InputStream inputStream = socket.getInputStream(); while (true) { int read = inputStream.read(bytes); if (read != -1) { System.out.println(new String(bytes, 0, read)); } else { break; } } } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("close connection..."); try { socket.close(); } catch (Exception e) { e.printStackTrace(); } } }
}
|
NIO - non-blocking IO
- 类和接口都在 java.nio 包中
- 同步非阻塞
- 三大核心组件:
Channel 通道
, Buffer 缓冲区
,Selector 选择器
- 以块的方式处理数据
- 每个channel都会对应一个buffer
- selector 对应一个线程,一个selector监听多个channel
- 程序切换到哪个channel是由事件event决定的
- channel是双向的,可以返回底层操作系统的情况
- buffer是一个内存块,是一个数组,可以读也可以写,需要flip方法切换
Buffer
Buffer是一个顶层抽象父类,层级关系如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| Buffer (java.nio) IntBuffer (java.nio) DirectIntBufferU (java.nio) ByteBufferAsIntBufferL (java.nio) DirectIntBufferS (java.nio) ByteBufferAsIntBufferB (java.nio) HeapIntBuffer (java.nio) FloatBuffer (java.nio) ByteBufferAsFloatBufferB (java.nio) DirectFloatBufferU (java.nio) ByteBufferAsFloatBufferL (java.nio) DirectFloatBufferS (java.nio) HeapFloatBuffer (java.nio) CharBuffer (java.nio) ByteBufferAsCharBufferL (java.nio) DirectCharBufferS (java.nio) StringCharBuffer (java.nio) HeapCharBuffer (java.nio) ByteBufferAsCharBufferB (java.nio) DirectCharBufferU (java.nio) DoubleBuffer (java.nio) HeapDoubleBuffer (java.nio) DirectDoubleBufferU (java.nio) ByteBufferAsDoubleBufferB (java.nio) DirectDoubleBufferS (java.nio) ByteBufferAsDoubleBufferL (java.nio) ShortBuffer (java.nio) DirectShortBufferU (java.nio) ByteBufferAsShortBufferL (java.nio) ByteBufferAsShortBufferB (java.nio) HeapShortBuffer (java.nio) DirectShortBufferS (java.nio) LongBuffer (java.nio) HeapLongBuffer (java.nio) ByteBufferAsLongBufferB (java.nio) DirectLongBufferU (java.nio) ByteBufferAsLongBufferL (java.nio) DirectLongBufferS (java.nio) ByteBuffer (java.nio) HeapByteBuffer (java.nio) MappedByteBuffer (java.nio)
|
Buffer类有四个属性:日常中主要使用的ByteBuffer
1 2 3 4 5 6 7 8 9 10 11 12 13
| public abstract class Buffer {
private int mark = -1; private int position = 0; private int limit; private int capacity; }
|
Buffer支持 put
和 get
操作,put
放什么进去,get
就应该通过相应的数据类型取出来,否则会报BufferUnderflowException
Channel
- BIO 中的 stream 是单向的,例如 FileInputStream 对象只能进行读取数据的操作,而 NIO 中的通道(Channel)是双向的,可以读操作,也可以写操作。
- Channel在NIO中是一个接口
1
| public interface Channel extends Closeable {}
|
- 常用的Channel类有:
FileChannel、DatagramChannel、ServerSocketChannel 和 SocketChannel。
Selector
netty的IO线程NioEventLoop汇聚了Selector选择器,可以做到一个单线程去管理多个通道,当该某个通道空闲时返回空,不会阻塞,而是去处理其他通道的数据。