8、IO模型部分实现推导
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.49.Final</version>
</dependency>
测试demo:
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.junit.Test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
public class MyNetty {
@Test
public void myBytebuf() {
// 池化的
// ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(8, 20);// 初始大小和最大大小
// 非池化的
ByteBuf buf = UnpooledByteBufAllocator.DEFAULT.heapBuffer(8, 20);
print(buf);
buf.writeBytes(new byte[]{1, 2, 3, 4});
print(buf);
buf.writeBytes(new byte[]{1, 2, 3, 4});
print(buf);
buf.writeBytes(new byte[]{1, 2, 3, 4});
print(buf);
buf.writeBytes(new byte[]{1, 2, 3, 4});
print(buf);
buf.writeBytes(new byte[]{1, 2, 3, 4});
print(buf);
// 写第6次会超出20上限,所以会报错
buf.writeBytes(new byte[]{1, 2, 3, 4});
print(buf);
}
public static void print(ByteBuf buf) {
System.out.println("buf.isReadable(): " + buf.isReadable()); // 是否可读
System.out.println("buf.readerIndex(): " + buf.readerIndex()); // 从哪读
System.out.println("buf.readableBytes(): " + buf.readableBytes()); // 读多少
System.out.println("buf.isWritable(): " + buf.isWritable()); // 是否可写
System.out.println("buf.writerIndex(): " + buf.writerIndex()); // 写的位置
System.out.println("buf.writableBytes(): " + buf.writableBytes()); // 写多少
System.out.println("buf.capacity(): " + buf.capacity()); // 真实分配的上限
System.out.println("buf.maxCapacity(): " + buf.maxCapacity()); // 期望的上限
System.out.println("buf.isDirect(): " + buf.isDirect()); // 是否为堆外分配
System.out.println("==========================================================================");
}
@Test
public void loopExecutor() throws IOException {
// 线程池,给定1个线程,就只有1个线程执行
NioEventLoopGroup selector = new NioEventLoopGroup(2);
selector.execute(() -> {
try {
for (; ; ) {
System.out.println("hello001");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// 因为给了2个线程,所以下面这个线程才会执行
selector.execute(() -> {
try {
for (; ; ) {
System.out.println("hello002");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.in.read();
}
/*
客户端连接别人:
1, 主动连接
2, 别人什么时候给我发?
*/
@Test
public void clientMode() throws Exception {
NioEventLoopGroup thread = new NioEventLoopGroup(1);
// 客户端模式
NioSocketChannel client = new NioSocketChannel();
thread.register(client); // 相当于epoll_ctl
// 响应式:
ChannelPipeline pipeline = client.pipeline();
pipeline.addLast(new MyInHandler());
// 在服务端开启端口测试是否连接: nc -l 10.10.10.101 9090
ChannelFuture connect = client.connect(new InetSocketAddress("10.10.10.101", 9090));
ChannelFuture sync = connect.sync();
ByteBuf buf = Unpooled.copiedBuffer("Hello Server".getBytes());
ChannelFuture send = client.writeAndFlush(buf);
send.sync();
sync.channel().closeFuture().sync();
// 服务端断开连接就打印
System.out.println("client over......");
}
/*
用户自己实现的
不应该加@ChannelHandler.Sharable这个给它
*/
private class MyInHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("client registed...");
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("client active...");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
// CharSequence str = buf.readCharSequence(buf.readableBytes(), StandardCharsets.UTF_8);
CharSequence str = buf.getCharSequence(0, buf.readableBytes(), StandardCharsets.UTF_8);
System.out.println(str);
ctx.writeAndFlush(buf);
}
}
@Test
public void serverMode() throws InterruptedException {
NioEventLoopGroup thread = new NioEventLoopGroup(1);
NioServerSocketChannel serverSocketChannel = new NioServerSocketChannel();
thread.register(serverSocketChannel);
// 不知道什么客户端连接,所以用响应式
ChannelPipeline pipeline = serverSocketChannel.pipeline();
// pipeline.addLast(new MyAcceptHandler(thread, new MyInHandler()));// accept接收客户端,并注册selector
pipeline.addLast(new MyAcceptHandler(thread, new ChannelInit()));// accept接收客户端,并注册selector
ChannelFuture bind = serverSocketChannel.bind(new InetSocketAddress("192.168.243.1", 9090));
bind.sync().channel().closeFuture().sync();
System.out.println("server close...");
}
@ChannelHandler.Sharable
private class ChannelInit extends ChannelInboundHandlerAdapter {
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
Channel client = ctx.channel();
ChannelPipeline pipeline = client.pipeline();
pipeline.addLast(new MyInHandler());
ctx.pipeline().remove(this);
}
}
private class MyAcceptHandler extends ChannelInboundHandlerAdapter {
private final EventLoopGroup selector;
private final ChannelHandler handler;
public MyAcceptHandler(EventLoopGroup thread, ChannelHandler myInHandler) {
this.selector = thread;
this.handler = myInHandler;
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("server registerd......");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
SocketChannel client = (SocketChannel) msg;
// 注册
selector.register(client);
// 响应式handler
ChannelPipeline pipeline = client.pipeline();
pipeline.addLast(handler);
}
}
// 官方写法
@Test
public void nettyClient() throws InterruptedException {
NioEventLoopGroup group = new NioEventLoopGroup(1);
Bootstrap bootstrap = new Bootstrap();
ChannelFuture channelFuture = bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new MyInHandler());
}
})
.connect(new InetSocketAddress("10.10.10.101", 9090));
Channel channel = channelFuture.sync().channel();
ByteBuf buf = Unpooled.copiedBuffer("hello server".getBytes());
ChannelFuture send = channel.writeAndFlush(buf);
send.sync();
channel.closeFuture().sync();
}
@Test
public void nettyServer() throws InterruptedException {
NioEventLoopGroup group = new NioEventLoopGroup(1);
ServerBootstrap serverBootstrap = new ServerBootstrap();
ChannelFuture channelFuture = serverBootstrap.group(group, group)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
ChannelPipeline pipeline = nioSocketChannel.pipeline();
pipeline.addLast(new MyInHandler());
}
})
.bind(new InetSocketAddress("192.168.243.1", 9090));
channelFuture.channel().closeFuture().sync();
}
}
《三体》中有句话——弱小和无知不是生存的障碍,傲慢才是。
所以我们不要做一个小青蛙