Netty服务器搭建

一、Netty服务器搭建步骤

  • 1) 构建一对主从线程池
  • 2) 为服务器设置channel
  • 3) 设置处理从线程池得助手类初始化起
  • 4) 监听启动和关闭服务器

设置Channel初始化器

每一个Channel都是由多个handler共同组成的管道(pipeline),每个管道都类似于一个小助手,需要程序员初始化时自动设置,一个管道可以理解为一个大的拦截器,而里面的handler可以理解为一个小的拦截器。

1. 定义服务启动类

package org.wdzl;

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;

/*
实现客户端发送请求,服务器给与响应 hello netty
 */
//每次客户端和服务器端连接后都会产生一个Channel对象
public class HelloNettyServer {
    public static void main(String[] args) throws Exception {
        //创建一组线程池组
        //主线程池: 用于接收客户端的请求链接,不做任务处理
        EventLoopGroup group1 = new NioEventLoopGroup();
        //从线程池: 主线程组会把任务交给它,让其做任务
        EventLoopGroup group2 = new NioEventLoopGroup();
        try{
            //创建服务器启动类
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(group1, group2) //设置主从线程池
                    .channel(NioServerSocketChannel.class) //设置nio双向通道
                    .childHandler(new HelloNettyServerInitializer()); //添加子处理器,用于处理从线程池交过来的任务
            //启动服务,并且设置端口号,同时启动的方式为同步
            ChannelFuture channelFuture = serverBootstrap.bind(8888).sync();
            //监听关闭的channel,设置为同步方式
            channelFuture.channel().closeFuture().sync();
        }finally {
            group1.shutdownGracefully(); //优雅得进行关闭
            group2.shutdownGracefully();
        }
    }

}

2. 定义服务器启动初始化类

package org.wdzl;

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 HelloNettyServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        //通过SocketChannel去获取对应的管道
        ChannelPipeline pipeline = channel.pipeline();
        //通过管道添加handler
        //new HttpServerCodec()是由netty自己提供的助手类,可以理解为拦截器
        //当请求到服务器,我们需要解码,响应到客户端需要做编码
        pipeline.addLast("HttpServerCodec", new HttpServerCodec());
        //添加自定义助手类,给客户端浏览器渲染hello netty~
        pipeline.addLast("CunstomHandler", new CustomHandler());
    }
}

3. 自定义Handler

package org.wdzl;

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> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        //获取channel
        Channel channel = ctx.channel();
        //需要先判断是否是HttpRequest 不然服务器端就会报错
        if(msg 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_0, HttpResponseStatus.OK, content);
            //为响应增加数据类型和长度
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());

            //把响应渲染到html客户端页面上
            ctx.writeAndFlush(response);
        }
    }

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

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

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

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

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

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

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

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

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

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

二、Channel的生命周期

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值