构建Netty的第一个服务器Hello Netty

概述

使用主从线程模型搭建服务器

  • 构建一对主从线程组
  • 定义服务器启动类
  • 为服务器设置Channel(每一个客户端需要在服务端注册一个channel数据通道)
  • 设置处理 从线程池 的助手类初始化器(处理子线程组助手类handler)
  • 监听启动和关闭服务器

步骤

绑定8088端口,采用不指定路由的方式,即所有访问localhost:8088的路由都能返回Hello Netty(比如localhost:8088/test)

创建Maven项目,pom中添加依赖(<dependencies></dependencies>中)

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.37.Final</version>
</dependency>

主体类(含有main方法) HelloServer.java

package com.imooc.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @Author Sakura
 * @Date 5/8/2019
 * @Description 客户端发送一个请求,服务端返回Hello Netty
 **/
public class HelloServer {

    public static void main(String[] args) throws Exception {

        //定义一对线程组
        //主线程组,接收客户端连接
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //从线程组,处理事件
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            //服务器创建,ServerBootstrap是启动类
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup,workerGroup)  //设置主从线程组
                    .channel(NioServerSocketChannel.class) //设置NIO双向通道
                    .childHandler(new HelloServerInitialiizer()); //子处理器,处理workerGroup

            //启动server,绑定8088端口,启动方式为同步
            ChannelFuture channelFuture = serverBootstrap.bind(8088).sync();

            //监听关闭的channel,设置为同步方式
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}

初始化器 HelloServerInitialiizer.java

package com.imooc.netty;

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

/**
 * @Author Sakura
 * @Date 5/8/2019
 * @Description 初始化器,channel注册后,执行相应初始化方法
 **/
public class HelloServerInitialiizer  extends ChannelInitializer<SocketChannel> {

    protected void initChannel(SocketChannel socketChannel) throws Exception {

        //通过socketChannel获得对应管道
        ChannelPipeline channelPipeline = socketChannel.pipeline();

        //通过管道,添加handler
        //HttpServerCodec是由Netty 提供的助手类。请求来到服务端时解码,响应到客户端时编码
        channelPipeline.addLast("HttpServerCodec",new HttpServerCodec());

        //添加自定义助手类,返回"hello netty"
        channelPipeline.addLast("customHandler",new CustomHandler());
    }
}

返回Hello Netty的助手类  CustomHandler.java

package com.imooc.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;


/**
 * @Author Sakura
 * @Date 5/8/2019
 * 创建自定义助手类
 **/

//SimpleChannelInboundHandler:对于请求,相当于[入站]
public class CustomHandler extends SimpleChannelInboundHandler<HttpObject> {
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject httpObject) throws Exception {

        //获取channel
        Channel channel = channelHandlerContext.channel();

        //仅处理HttpRequest请求
        if(httpObject instanceof HttpRequest){
            //显示客户端远程地址
            System.out.println(channel.remoteAddress());

            //定义发送的数据
            ByteBuf content = Unpooled.copiedBuffer("Hello Netty~", CharsetUtil.UTF_8);

            //构建一个http response
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
                    HttpResponseStatus.OK,content);
            //为响应增加数据类型和长度
            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());

            //把响应刷新到客户端
            channelHandlerContext.writeAndFlush(response);

        }

    }
}

测试

启动项目后,浏览器输入localhost:8088

控制台显示

为什么显示两条那,打开请求网页的开发者工具,network栏目,刷新网页重新请求,发现有两条请求(下边的请求为图标请求)

可以使用命令行(cmd)进行纯净的请求

此时控制台只有一条

发布了154 篇原创文章 · 获赞 55 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/weixin_42089175/article/details/98480493