Netty入门

官网

https://netty.io/

Netty is an asynchronous event-driven network application framework
for rapid development of maintainable high performance protocol servers & clients.

Netty是一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端。

客户端发送,服务端接收案例

// 服务端
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ServerDemo {
    private static final Logger log = LoggerFactory.getLogger(ServerDemo.class);

    public static void main(String[] args) {
        // 启动服务器
        new ServerBootstrap()
                // 设置线程组
                .group(new NioEventLoopGroup())
                // ServerSocketChannel模式选择
                .channel(NioServerSocketChannel.class)
                // worker处理连接
                .childHandler(
//                        通道初始化,添加handler
                        new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
//                        将buffer转为字符串
                        nioSocketChannel.pipeline().addLast(new StringDecoder());
//                        自定义处理器
                        nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                            @Override
                            public void channelRead(ChannelHandlerContext ctx,Object msg)throws Exception {
                                log.info(msg.toString());
                            }
                        });
                    }
                })
//                绑定端口
                .bind(8090);
    }
}

// 客户端
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;

public class ClientDemo {
    public static void main(String[] args) throws InterruptedException {
//        启动类
        new Bootstrap()
//                添加eventloop
                .group(new NioEventLoopGroup())
//                选择客户端实现
                .channel(NioSocketChannel.class)
//                添加处理器
                .handler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                        nioSocketChannel.pipeline().addLast(new StringEncoder());
                    }
                })
                // 连接到服务器
                .connect("localhost",8090)
                // 阻塞方法,直到连接建立
                .sync()
                // 获取连接对象
                .channel()
                // 向服务器发送数据
                .writeAndFlush("微信小程序:马上行计划管理,欢迎体验。");
    }
}

客户端调试idea设置

允许启动多实例
在这里插入图片描述
启用多线程调试,断点处右键
在这里插入图片描述

netty常用组件

EventLoop

本质是一个单线程执行器维护了一个Selector,管理channel。
public interface EventLoop extends OrderedEventExecutor, EventLoopGroup

Channel

建立连接后channel与EventLoop绑定。

Future和Promise

    @Test
    public void testJdkFeature() throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        Future<Integer> submit = executor.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                log.info("Callable");
                Thread.sleep(1000);
                return 10;
            }
        });
        log.info("执行完成submit");
        log.info("等待结果{}", submit.get());
    }

    @Test
    public void testNettyFeature() throws Exception {
        NioEventLoopGroup group = new NioEventLoopGroup();
        try {
            EventLoop next = group.next();
            io.netty.util.concurrent.Future<Integer> future = next.submit(() -> {
                log.info("Callable");
                Thread.sleep(1000);
                return 20;
            });

            // 使用CountDownLatch等待异步操作完成
            CountDownLatch latch = new CountDownLatch(1);

            future.addListener((GenericFutureListener<io.netty.util.concurrent.Future<? super Integer>>) f -> {
                try {
                    log.info("等待结果{}", f.getNow());
                } finally {
                    latch.countDown();
                }
            });

            log.info("执行完成submit");

            // 等待异步操作完成,设置合理的超时时间
            assertTrue(latch.await(2, TimeUnit.SECONDS));
        } finally {
            group.shutdownGracefully().sync();
        }
    }

    @Test
    public void testNettyPromise() throws Exception{
        EventLoop next = new NioEventLoopGroup().next();
        DefaultPromise<Integer> promise = new DefaultPromise<>(next);
        new Thread(()->{
            log.info("新线程开始");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            promise.setSuccess(30);
        }).start();
        log.debug("等待结束");
        // 等待异步操作完成,设置合理的超时时间
        log.info("计算结果是{}",promise.get());
    }

Handler和Pipline

Pipline相当于一个流水线,而Handler则相当于流水线每一个工序。
Hander分为入站和出栈两种类型。

pipline执行handler数序

public class PiplineDemo {
    static final Logger log = LoggerFactory.getLogger(PiplineDemo.class);

    public static void main(String[] args) {

        // 启动服务器
        new ServerBootstrap()
                // 设置线程组
                .group(new NioEventLoopGroup(),new NioEventLoopGroup())
                // ServerSocketChannel模式选择
                .channel(NioServerSocketChannel.class)
                // worker处理连接,一个channel绑定一个eventloop
                .childHandler(
//                        通道初始化,添加handler
                        new ChannelInitializer<NioSocketChannel>() {
                            @Override
                            protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                                ChannelPipeline pipeline = nioSocketChannel.pipeline();
//                                处理器head->first->second->third->sixth->fifth->fourth->tail
                                pipeline.addLast("first",new ChannelInboundHandlerAdapter(){
                                    public void channelRead(ChannelHandlerContext ctx,Object message) throws Exception {
                                        log.info("first");
                                        super.channelRead(ctx,message);
                                    }
                                });
                                pipeline.addLast("second",new ChannelInboundHandlerAdapter(){
                                    public void channelRead(ChannelHandlerContext ctx,Object message) throws Exception {
                                        log.info("second");
                                        super.channelRead(ctx,message);
                                    }
                                });
                                pipeline.addLast("third",new ChannelInboundHandlerAdapter(){
                                    public void channelRead(ChannelHandlerContext ctx,Object message) throws Exception {
                                        log.info("third");
//                                        super.channelRead(ctx,message);
//                                        使用nioSocketChannel从tail往前走所有的出站处理器
//                                        nioSocketChannel.writeAndFlush(ctx.alloc().buffer().writeBytes("欢迎使用微信小程序马上行计划管理".getBytes()));
//                                        使用ctx从当前位置往前找出站处理器
                                        ctx.writeAndFlush(ctx.alloc().buffer().writeBytes("欢迎使用微信小程序马上行计划管理".getBytes()));
                                    }
                                });
                                pipeline.addLast("fourth",new ChannelOutboundHandlerAdapter(){
                                    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                                        log.info("fourth");
                                        super.write(ctx,msg,promise);
                                    }
                                });
                                pipeline.addLast("fifth",new ChannelOutboundHandlerAdapter(){
                                    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                                        log.info("fifth");
                                        super.write(ctx,msg,promise);
                                    }
                                });
                                pipeline.addLast("sixth",new ChannelOutboundHandlerAdapter(){
                                    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                                        log.info("sixth");
                                        super.write(ctx,msg,promise);
                                    }
                                });
                            }
                        })
//                绑定端口
                .bind(8090);
    }
}

测试handler及顺序

    private static final Logger log = LoggerFactory.getLogger(ClientDemo.class);
    public static void main(String[] args) {
        ChannelInboundHandlerAdapter first=new ChannelInboundHandlerAdapter(){
            public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
                log.info("first");
                super.channelRead(ctx,message);
            }
        };
        ChannelInboundHandlerAdapter second=new ChannelInboundHandlerAdapter(){
            public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
                log.info("second");
                super.channelRead(ctx,message);
            }
        };
        ChannelOutboundHandlerAdapter fourth=new ChannelOutboundHandlerAdapter(){
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                log.info("fourth");
                super.write(ctx,msg,promise);
            }
        };
        ChannelOutboundHandlerAdapter fifth=new ChannelOutboundHandlerAdapter(){
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                log.info("fifth");
                super.write(ctx,msg,promise);
            }
        };
        EmbeddedChannel channel = new EmbeddedChannel(first,second,fourth,fifth);
//        模拟入栈
        channel.writeInbound("欢迎使用微信小程序马上行计划管理".getBytes());
//        模拟出站
        channel.writeOutbound("欢迎使用微信小程序马上行计划管理".getBytes());
    }

ByteBuf

自动扩容,内存管理使用引用计数器法。

        // 堆内存
        ByteBufAllocator.DEFAULT.heapBuffer();
        // 直接内存
        ByteBufAllocator.DEFAULT.directBuffer();

此文技术,助力微信小程序:马上行计划管理。
欢迎体验,微信搜索马上行计划管理,或者扫码
在这里插入图片描述

### Netty 入门教程 Netty 是一款基于 Java 的高性能网络应用框架,它简化了 TCP 和 UDP 协议的开发过程。以下是关于 Netty 基础知识和入门使用的详细介绍。 #### 1. Netty 概述 Netty 提供了一种异步事件驱动的方式来处理网络通信,使得开发者可以专注于业务逻辑而无需过多关注底层细节[^2]。相比于直接使用 JDK 的 NIO 类库,Netty 封装了许多复杂的实现细节,从而降低了开发难度并提高了效率[^3]。 #### 2. Netty 的核心组件 - **Channel**: 表示一个连接到实体(例如套接字)的对象,用于执行 I/O 操作。 - **EventLoop**: 负责监听 Channel 上发生的事件,并将其传递给相应的处理器。 - **ChannelPipeline & ChannelHandler**: 组件链表结构,负责拦截入站和出站的数据流,允许自定义行为来处理请求或响应。 这些概念构成了 Netty 架构的核心部分[^1]。 #### 3. 创建一个简单的 HTTP Server 为了更好地理解如何实际运用 Netty 来构建项目,这里提供了一个基本的例子——创建一个支持 GET 请求的小型 Web 服务器: ```java import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; public class SimpleHttpServer { public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1) EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); // (2) b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // (3) .childHandler(new HttpInitializer()); // (4) ChannelFuture f = b.bind(8080).sync(); // (5) System.out.println("HTTP server started at http://localhost:8080/"); f.channel().closeFuture().sync(); // (6) } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } } ``` 上述代码展示了如何初始化 Netty 并绑定端口以等待客户端连接。 #### 4. 解决常见问题 - 粘包/拆包现象 当涉及到二进制协议或者大文件传输时,可能会遇到数据帧被分割成多个片段的情况。为此,Netty 提供了几种内置解码器解决方案,如 `LineBasedFrameDecoder`、`DelimiterBasedFrameDecoder` 和 `FixedLengthFrameDecoder` 等[^5]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值