Netty保姆级入门教程

简介: Netty保姆级入门教程

今天是实战篇,没有理论,只是记录一下使用Netty搭建一个本地服务,实现客户端数据发送到服务端数据Demo的教程,理论篇以及更深层次学习Netty可以点个关注,保证后续更新不错过!!!

搭建Netty服务端

服务端

使用main方法的形式构建,启动在本地8888端口

package com.zuiyu.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
 * @author @醉鱼
 * @link https://github.com/TianPuJun
 * @ClassName NettyService
 * @Description
 * @Date 22:05 2022/6/28
 **/
public class NettyService {
    public static void main(String[] args) throws InterruptedException {
        // 用于接收客户端链接的线程工作组
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        // 用于接收客户端链接读写操作的线程组
        EventLoopGroup workGroup = new NioEventLoopGroup();
        // 辅助类,帮助创建netty服务
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap
                // 绑定两个工作组
                .group(eventLoopGroup,workGroup)
                // 设置nio 模式
                .channel(NioServerSocketChannel.class)
                // option 针对服务器端配置,childOption 针对客户端链接通道配置
                // 设置tcp 缓冲区
                .option(ChannelOption.SO_BACKLOG,1024)
                // 设置发送数据的缓存大小
                .childOption(ChannelOption.SO_SNDBUF,32*1024)
                // 设置读取数据的缓存大小
                .childOption(ChannelOption.SO_RCVBUF,32*1024)
                // 设置保持长链接
                .childOption(ChannelOption.SO_KEEPALIVE,true)
                // 初始化绑定服务通道
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        // 为通道进行初始化,数据传输过来的适合会进行拦截和执行(可以有多个拦截器)
                        socketChannel.pipeline().addLast(new ServerHandler());
                    }
                });
        ChannelFuture sync = serverBootstrap.bind(8888).sync();
        // 释放链接
        sync.channel().closeFuture().sync();
        workGroup.shutdownGracefully();
        eventLoopGroup.shutdownGracefully();
    }
}

服务端监听

新建ServerHandler监听数据

package com.zuiyu.netty;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import java.util.logging.Logger;
/**
 * @author @醉鱼
 * @link https://github.com/TianPuJun
 * @ClassName ServerHandler
 * @Description 服务回调
 * @Date 22:15 2022/6/28
 **/
public class ServerHandler extends ChannelInboundHandlerAdapter {
    public static final Logger LOGGER = Logger.getLogger("ServerHandler");
    public ServerHandler() {
        super();
    }
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
    }
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
    }
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        LOGGER.info("======服务端通道激活======");
    }
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
    }
    /**
     * 当通道有数据读取时的监听
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            // 传输buffer 对象
            ByteBuf buf = (ByteBuf)msg;
            // 定义byte数组
            byte[] req =new byte[buf.readableBytes()];
            // 从缓冲区获取数据到req
            buf.readBytes(req);
            // 读取数据转为字符串
            String body = new String(req,"utf-8");
            LOGGER.info("服务端读取的数据:"+body);
            // 响应给客户端的数据
            ctx.writeAndFlush(Unpooled.copiedBuffer("netty server response data: you are beautiful".getBytes()))
            // 添加addListener可以触发关闭通道监听事件,客户端短链接场景使用
            // .addListener(ChannelFutureListener.CLOSE);
            ;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            ReferenceCountUtil.release(msg);
        }
    }
    /**
     * 当我们读取完成数据时触发的操作
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        LOGGER.info("====== 服务端数据读取完成 ======");
    }
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        super.userEventTriggered(ctx, evt);
    }
    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        super.channelWritabilityChanged(ctx);
    }
    /**
     * 当我们读取数据异常的时候触发的监听
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        LOGGER.info("====== 服务端数据读取异常 ======");
        LOGGER.info(cause.getMessage());
        ctx.close();
    }
}

搭建Netty客户端

客户端

同样适用main方法的形式搭建测试,发送数据到本地8888端口

package com.zuiyu.netty;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
 * @author @醉鱼
 * @link https://github.com/TianPuJun
 * @ClassName NettyClient
 * @Description
 * @Date 22:27 2022/6/28
 **/
public class NettyClient {
    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup eventExecutors = new NioEventLoopGroup();
        Bootstrap b = new Bootstrap();
        b.group(eventExecutors)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(new ClientHandler());
                    }
                });
        ChannelFuture channelFuture = b.connect("127.0.0.1", 8888).syncUninterruptibly();
        channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer("netty 客户端请求数据:zuiyu netty 服务发送数据测试".getBytes()));
        // 释放链接
        channelFuture.channel().closeFuture().sync();
    }
}

客户端监听

新建客户端监听ClientHandler,发送数据时打印数据

package com.zuiyu.netty;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import java.util.logging.Logger;
/**
 * @author @醉鱼
 * @link https://github.com/TianPuJun
 * @ClassName ClientHandler
 * @Description
 * @Date 22:32 2022/6/28
 **/
public class ClientHandler extends ChannelInboundHandlerAdapter {
    public static final Logger LOGGER = Logger.getLogger("ClientHandler");
    public ClientHandler() {
        super();
    }
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
    }
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
    }
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        LOGGER.info("====== 客户端通道激活======");
    }
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
    }
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            // 传输buffer 对象
            ByteBuf buf = (ByteBuf)msg;
            // 定义byte数组
            byte[] req =new byte[buf.readableBytes()];
            // 从缓冲区获取数据到req
            buf.readBytes(req);
            // 读取数据转为字符串
            String body = new String(req,"utf-8");
            LOGGER.info("客户端读取的数据:"+body);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            ReferenceCountUtil.release(msg);
        }
    }
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        LOGGER.info("====== 客户端读取数据完毕======");
    }
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        super.userEventTriggered(ctx, evt);
    }
    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        super.channelWritabilityChanged(ctx);
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        LOGGER.info("====== 客户端读取数据异常======");
        ctx.close();
    }
}

验证打印输出

  • 先启动NettyServer#main
  • 再启动NettyClient#main
  • 结果如下

Demo 教程到此结束,只为记录过程,代码详细位置NettyServer中都有注释,觉得有帮助动动小手点个关注再走哦,点关注不迷路

Demo 地址 :

https://github.com/TianPuJun/spring-notes/tree/master/netty

本文由 mdnice 多平台发布

目录
相关文章
|
3月前
|
缓存 网络协议 算法
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析
143 0
|
1月前
|
网络协议 Java 测试技术
阿里内部Netty实战小册,值得拥有
Netty 是一个高性能的 Java 网络通信框架,简化了网络编程并涵盖了最新的Web技术。它提供了一种抽象,降低了底层复杂性,使得更多开发者能接触网络编程。Netty 因其易用性、高效性和广泛的应用场景受到推崇,适合互联网行业从业者学习,有助于理解和开发基于Netty的系统。免费的《Netty实战小册》详细介绍了Netty的各个方面,包括概念、架构、编解码器、网络协议和实际案例,帮助读者深入理解和应用Netty。如需完整版小册,可点击链接获取。
阿里内部Netty实战小册,值得拥有
|
1月前
|
监控 Java 测试技术
拆帧神器:深度解读Netty中的DelimiterBasedFrameDecoder()
拆帧神器:深度解读Netty中的DelimiterBasedFrameDecoder()
38 0
|
3月前
|
消息中间件 缓存 Java
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty
99 0
|
10月前
|
存储 前端开发 网络协议
Netty入门到超神系列-Netty入门&核心类
我们需要有GoosGroup来循环监听请求事件,需要有WorkGroup来处理事件,而这两个角色都通过来就NioEventLoopGroup来进行事件监听,我们还需要创建事件处理器ChannelHandler,通过 Channel的ChannelPipeline把ChannelHandler进行关联。
95 0
|
5月前
|
缓存 网络协议 算法
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析(二)
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析
61 1
|
5月前
|
设计模式 网络协议 算法
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析(一)
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析(一)
93 1
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析(一)
|
5月前
|
缓存 Java 数据挖掘
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty(一)
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty
89 0
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty(一)
|
5月前
|
消息中间件 缓存 Java
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty(二)
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty
109 1
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty(二)
|
5月前
|
消息中间件 编解码 Java
京东T8全面详解Java开源框架,透彻剖析尽在《Netty权威指南》
随着大规模分布式系统、大数据和流式计算框架的兴起,基于Java来构建这些系统已经成为主流,NIO编程和NIO框架在此期间得到了大规模的商用。在互联网领域,阿里的分布式服务框架Dubbo、RocketMQ,大数据的基础序列化和通信框架Avro, 以及很多开源的软件都已经开始使用Netty来构建高性能、分布式通信能力,Netty社区的活跃度也名列前茅。