用Idea搭建簡單的Netty服務器

本文使用netty自定義了一個http協議的服務器。

1.創建一個maven項目,在pom.xml文件中導入依賴並刷新

<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
    <dependency>
      <groupId>io.netty</groupId>
      <artifactId>netty-all</artifactId>
      <version>4.1.16.Final</version>
    </dependency>

2.搭建一個Netty服務器,我們只需要兩個類——一個是啓動類,負責啓動(BootStrap)和main方法;一個是ChannelHandler,負責具體的業務邏輯。

啓動類:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

import java.util.Date;

/**
 * Created by RoyDeng on 20/03/22.
 */
public class HttpServer {

    private final static int port = 8080;


    public static void main(String[] args) throws Exception {
        System.out.println(new Date().toLocaleString()+"netty服務器啓動了");
        start();
    }

    public static void start() throws Exception {
        //ServerBootstrap作爲一個啓動輔助類,通過他可以很方便的創建一個Netty服務端
        ServerBootstrap b = new ServerBootstrap();
        //創建線程池
        NioEventLoopGroup group = new NioEventLoopGroup();
        b.group(group)
                //指定使用NioServerSocketChannel來處理連接請求,放射生成一個channel連接
                .channel(NioServerSocketChannel.class)
                //配置handler和childHandler,數據處理器
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch)
                            throws Exception {
                        System.out.println("initChannel ch:" + ch);
                        ch.pipeline()
                                // HttpRequestDecoder,用於解碼request
                                .addLast("decoder", new HttpRequestDecoder()) 
                                // HttpResponseEncoder,用於編碼response  
                                .addLast("encoder", new HttpResponseEncoder()) 
                                //aggregator消息聚合器,參數含義是消息合併的數據大小,如此代表聚合的消息內容長度不超過512kb
                                .addLast("aggregator", new HttpObjectAggregator(512 * 1024))
                                //添加我們自己的處理接口
                                .addLast("handler", new HttpHandler());        // 4
                    }
                })
                .option(ChannelOption.SO_BACKLOG, 128) // 配置TCP參數
                .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);//
        //啓動服務器
        b.bind(port).sync();
    }
}

handler線程處理類

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.AsciiString;

import java.util.Date;

/**
 * Handler需要聲明泛型爲<FullHttpRequest>,聲明之後,只有msg爲FullHttpRequest的消息才能進來
 */
public class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    private AsciiString contentType = HttpHeaderValues.TEXT_PLAIN;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
        System.out.println(new Date().toLocaleString()+"class:" + msg.getClass().getName());
        /*
        生成response,使用的FullHttpResponse,同FullHttpRequest類似,
        通過這個我們就不用將response拆分成多個channel返回給請求端了
        */
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
                HttpResponseStatus.OK,
                // 響應內容:test --> 使用平臺的默認字符集將字符串編碼爲 byte 序列,存爲新的 byte 數組中
                Unpooled.wrappedBuffer("test".getBytes()));

        HttpHeaders heads = response.headers();
        //定義響應頭的content_type、content_length、connection:keep_alive
        heads.add(HttpHeaderNames.CONTENT_TYPE, contentType + "; charset=UTF-8");
        heads.add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()); // 3
        heads.add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);

        ctx.write(response);
    }
    //讀取完成,輸出緩衝流
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println(new Date().toLocaleString()+"channelReadComplete");
        super.channelReadComplete(ctx);
        //清空連接數據
        ctx.flush();
    }

    //異常捕獲
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("exceptionCaught");
        if(null != cause) cause.printStackTrace();
        if(null != ctx) ctx.close();
    }
}

運行,瀏覽器輸入:http://localhost:8080

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