1.三大组件
1.1 Channel&Buffer
常见的Channel有以下四种,其中FileChannel主要用于文件传输,其余三种用于网络通信
FileChannel
DatagramChannel
SocketChannel
ServerSocketChannel
Buffer有以下几种,其中使用较多的是ByteBuffer
ByteBuffer
MappedByteBuffer
DirectByteBuffer
HeapByteBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
CharBuffer
1.2Selector
多线程版设计:
适合连接数少的场景
线程池版设计:
适合短连接场景
Selector版设计:
适合连接数特别多,但流量低的场景
2.bytebuffer基本使用
package com.ityin.netty.c1;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class TestByteBuffer {
public static void main(String[] args) {
//FileChannel
//1.输入输出流
//2.RandomAccessFile
try (FileChannel channel=new FileInputStream("data.txt").getChannel()) {
System.out.println("111");
//准备缓冲区
ByteBuffer buffer=ByteBuffer.allocate(10);
//从Channel读取数据,向Buffer写入
channel.read(buffer);
//打印Buffer内容
buffer.flip();//切换至读模式
while(buffer.hasRemaining()){//是否还有剩余数据
byte b=buffer.get();
System.out.println((char) b);
}
} catch (IOException e){
}
}
}
由于以上代码只能输出有限个字符,不能保证输出全部字符,所以可以改进为:
package com.ityin.netty.c1;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class TestByteBuffer {
public static void main(String[] args) {
//FileChannel
//1.输入输出流
//2.RandomAccessFile
try (FileChannel channel=new FileInputStream("data.txt").getChannel()) {
//准备缓冲区
ByteBuffer buffer=ByteBuffer.allocate(10);
//从Channel读取数据,向Buffer写入
//channel.read(buffer);
//打印Buffer内容
while (true){
int len=channel.read(buffer);
if(len==-1){
break;
}
buffer.flip();//切换至读模式
while(buffer.hasRemaining()){//是否还有剩余数据
byte b=buffer.get();
System.out.println((char) b);
}
//切换为写模式
buffer.clear();
}
} catch (IOException e){
}
}
}
bytebuffer方法演示1:
bytebuffer方法演示2:
public class TestByteBufferAllocate {
public static void main(String[] args) {
System.out.println(ByteBuffer.allocate(16).getClass());
System.out.println(ByteBuffer.allocateDirect(16).getClass());
/*
HeapByteBuffer -java堆内存,读写效率较低,受到GC影响
DirectByteBuffer -直接内存,读写效率高(少一次Copy),不会受GC影响,因为是系统内存,分配效率变低,要合理释放
*/
}
}
bytebuffer方法演示3,mark和reset的使用:
package com.ityin.netty.c1;
import java.nio.ByteBuffer;
import static com.ityin.netty.c1.ByteBufferUtil.debugAll;
public class TestByteBufferRead {
public static void main(String[] args) {
ByteBuffer buffer =ByteBuffer.allocate(10);
buffer.put(new byte[]{'a','b','c','d'});
buffer.flip();
// //从头开始读
// buffer.get(new byte[3]);
// debugAll(buffer);
// buffer.rewind();
// System.out.println((char)buffer.get());
//mark&reset
//mark做一个标记,记录position位置,reset是将position重置到mark位置
System.out.println((char) buffer.get());
System.out.println((char) buffer.get());
buffer.mark();//加标记,索引2的位置
System.out.println((char) buffer.get());
System.out.println((char) buffer.get());
buffer.reset();//将position重置到索引2
System.out.println((char) buffer.get());
System.out.println((char) buffer.get());
}
}
bytebuffer方法演示4:字符串和ByteBuffer字符转换
package com.ityin.netty.c1;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static com.ityin.netty.c1.ByteBufferUtil.debugAll;
public class TestByteBufferString {
public static void main(String[] args) {
//1.字符串转为ByteBuffer,完成之后是写模式
ByteBuffer buffer =ByteBuffer.allocate(16);
buffer.put("hello".getBytes());
debugAll(buffer);
//2.Charset,完成之后是读模式
// Charset.defaultCharset(); //选择操作系统默认字符集
ByteBuffer buffer2=StandardCharsets.UTF_8.encode("hello"); //标准字符集
debugAll(buffer2);
//3.wrap
ByteBuffer buffer3=ByteBuffer.wrap("hello".getBytes());
debugAll(buffer3);
}
}
演示结果:
+--------+-------------------- all ------------------------+----------------+
position: [5], limit: [16]
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00 |hello...........|
+--------+-------------------------------------------------+----------------+
+--------+-------------------- all ------------------------+----------------+
position: [0], limit: [5]
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 68 65 6c 6c 6f |hello |
+--------+-------------------------------------------------+----------------+
+--------+-------------------- all ------------------------+----------------+
position: [0], limit: [5]
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 68 65 6c 6c 6f |hello |
+--------+-------------------------------------------------+----------------+
Process finished with exit code 0
Scattering Reads和Gathering Writes
Scattering Reads示例:
package com.ityin.netty.c1;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import static com.ityin.netty.c1.ByteBufferUtil.debugAll;
public class TestScatteringRead {
public static void main(String[] args) {
try (FileChannel channel=new RandomAccessFile("words.txt","r").getChannel()){
ByteBuffer b1=ByteBuffer.allocate(3);
ByteBuffer b2=ByteBuffer.allocate(3);
ByteBuffer b3=ByteBuffer.allocate(5);
channel.read(new ByteBuffer[]{b1,b2,b3});
b1.flip();
b2.flip();
b3.flip();
debugAll(b1);
debugAll(b2);
debugAll(b3);
} catch (IOException e) {
}
}
}
结果显示:
+--------+-------------------- all ------------------------+----------------+
position: [0], limit: [3]
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 6f 6e 65 |one |
+--------+-------------------------------------------------+----------------+
+--------+-------------------- all ------------------------+----------------+
position: [0], limit: [3]
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 74 77 6f |two |
+--------+-------------------------------------------------+----------------+
+--------+-------------------- all ------------------------+----------------+
position: [0], limit: [5]
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 74 68 72 65 65 |three |
+--------+-------------------------------------------------+----------------+
Process finished with exit code 0
Gathering Writes示例:
package com.ityin.netty.c1;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
public class TestGatheringWrite {
//集中写入
public static void main(String[] args) {
ByteBuffer b1= StandardCharsets.UTF_8.encode("hello");
ByteBuffer b2=StandardCharsets.UTF_8.encode("world");
ByteBuffer b3=StandardCharsets.UTF_8.encode("你好");
try(FileChannel channel=new RandomAccessFile("words2.txt","rw").getChannel()){
channel.write(new ByteBuffer[]{b1,b2,b3});
}catch(IOException e){
}
}
}
显示结果:
黏包半包解析: