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. 瀏覽效果

瀏覽器

在這裏插入圖片描述

控制檯

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章