Netty 一个简单的测试

1. 导包

        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.50.Final</version>
        </dependency>
        <dependency>
            <groupId>com.corundumstudio.socketio</groupId>
            <artifactId>netty-socketio</artifactId>
            <version>1.7.17</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

2. 测试类

package com.springCloud.netty;

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;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * 实现客户端发送请求, 服务器给予响应
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = NettyApplication.class)
public class NettyTest {

    @Test
    public void test() {
        // 创建一组线程组
        // 主线程: 用于接受客户端的请求链接, 不做任何处理
        EventLoopGroup group_main = new NioEventLoopGroup();
        // 从线程: 主线程池会把任务交给它, 让其做任务
        EventLoopGroup group_from = new NioEventLoopGroup();
        // 创建服务器启动类
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(group_main, group_from) // 设置主从线程
                .channel(NioServerSocketChannel.class) // 设置 NIO 的双向频道
                .childHandler(new NettyServerInitializer()); // 添加子处理器, 用于处理从线程池的任务
        try {
            // 启动服务并设置端口号, 同时启动方式为同步
            ChannelFuture sync = serverBootstrap.bind(8009).sync();
            // 监听关闭 Channel, 设置为同步方式.
            sync.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}

2. 初始化器

package com.springCloud.netty;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;

/**
 * 初始化器, channel 注册之后, 会执行里面的相应的初始化方法
 */
public class NettyServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        // 通过 SocketChannel 去获取对应的管道
        ChannelPipeline pipeline = socketChannel.pipeline();
        // 通过管道添加 handler, HttpServerCode: 是由 netty 自己提供的助手类, 可以理解为拦截器, 当请求到服务器, 我们需要解码, 响应到客户端做解码
        pipeline.addLast("HttpServerCodec", new HttpServerCodec());
        // 添加自定义助手类, 给客户端浏览器渲染内容
        pipeline.addLast("CustomHandler", new CustomHandler());
    }

}

3. 自定义助手类

package com.springCloud.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

/**
 * 自定义助手类
 */
public class CustomHandler extends SimpleChannelInboundHandler<HttpObject> {


    /**
     *
     * @param channelHandlerContext channelHandlerContext
     * @param httpObject httpObject
     * @throws Exception Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject httpObject) throws Exception {
        // 获取 channel
        Channel channel = channelHandlerContext.channel();
        // 在控制台打印远程地址
        System.out.println(channel.remoteAddress());
        // 定义向客户端发送的数据内容
        ByteBuf content = Unpooled.copiedBuffer("Hello netty", CharsetUtil.UTF_8);
        // 定义 Http response
        DefaultFullHttpResponse defaultFullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
        // 为响应增加数据类型和长度
        defaultFullHttpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
        defaultFullHttpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
        // 把响应渲染到 Html 客户端页面上
        channelHandlerContext.writeAndFlush(defaultFullHttpResponse);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
        System.out.println("Channel 注册");
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
        System.out.println("Channel 移除");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        System.out.println("Channel 活跃");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        System.out.println("Channel 不活跃");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
        System.out.println("Channel 读取完毕");
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        super.userEventTriggered(ctx, evt);
        System.out.println("用户事件触发");
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        super.channelWritabilityChanged(ctx);
        System.out.println("Channel 可写更改");
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        super.handlerAdded(ctx);
        System.out.println("助手类的添加");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        System.out.println("捕获到异常");
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        super.handlerRemoved(ctx);
        System.out.println("助手类的移除");
    }
}

4. 浏览效果

浏览器

在这里插入图片描述

控制台

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/YKenan/article/details/106362104
今日推荐