网络I/o编程模型14 netty的http协议服务器

本文档展示了如何使用Netty构建一个HTTP服务器,监听6666端口,接收到浏览器请求后,服务器会回应消息,并对特定资源进行过滤。当请求包含非指定路径时,服务器将忽略该请求并返回提示信息。

一 案例

1.1 案例描述

1.netty服务器使用6666端口监听,浏览器发送的请求:http://localhost:6666/

2.服务器收到消息后,向浏览器发送消息“hello,我是服务器,你在干什么!!!”,并对特定资源进行过滤。

1.2 代码

1.server端

package com.ljf.netty.netty.http;

import com.ljf.netty.netty.tcp.NettyTcpServerHandler3;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @ClassName: NettyHttpServer
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2022/05/30 09:10:05
 * @Version: V1.0
 **/
public class NettyHttpServer {
    public static void main(String[] args) {
        //创建连个线程组bossGroup和workerGroup
        EventLoopGroup bossGroup=new NioEventLoopGroup(1);//默认为cpu核数*2;
        EventLoopGroup workGroup=new NioEventLoopGroup();
        try {
        //创建服务器端的启动对象,配置参数
        ServerBootstrap bootstrap=new ServerBootstrap();
        //使用链式编程来进行设置
        bootstrap.group(bossGroup,workGroup) //设连个线程组
                .channel(NioServerSocketChannel.class) //使用NioSocketChannel作为服务器的通道实现
               // .option(ChannelOption.SO_BACKLOG,128)//设置线程队列得到的连接个数
                //.childOption(ChannelOption.SO_KEEPALIVE,true)  //设置保持活动连接状态
                .childHandler(new NettyHttpInitializer());//给我们的workerGroup的EventLopp对应的管道设置处理器,自定义的。
        System.out.println(".......netty服务器 is ready.....");
        //启动服务器(并绑定端口)
        ChannelFuture channelFuture=bootstrap.bind(6666).sync();
        //对关闭的通道进行监听
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}

2.适配器

public class NettyHttpInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
           //向管道加入处理器
        //得到管道
        ChannelPipeline pipeline=ch.pipeline();
        //加入一个解码器,HttpServerCodec 是netty提供的处理http的编-解码器
        pipeline.addLast("MyHttpServerCodec",new HttpServerCodec());
        // 增加一个自定义的 handler
        pipeline.addLast("MyDefineHandler",new DefineServerHandler());
    }
}

3.自定义handler

package com.ljf.netty.netty.http;

import io.netty.buffer.ByteBuf;
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.CharsetUtil;

import java.net.URI;

/**
 * @ClassName: DefineServerHandler
 * @Description: TODO
 *    simpleChannelInboundHandler 是 ChannelInboundHandlerAdapter
 *    HttpObject 客户端和服务器端相互通讯的数据被封装成 HttpObject
 * @Author: liujianfu
 * @Date: 2022/05/30 10:55:11
 * @Version: V1.0
 **/
public class DefineServerHandler extends SimpleChannelInboundHandler<HttpObject> {
    // 读取客户端数据
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
            //判断msg 是不是httprequest请求
        if(msg instanceof HttpRequest){
            System.out.println("pipeline hashcode:"+ctx.pipeline().hashCode()+" handler hash:"+this.hashCode());
            System.out.println("msg 类型: "+msg.getClass());
            System.out.println("客户端地址:"+ctx.channel().remoteAddress());
            //获取到
            HttpRequest httpRequest=(HttpRequest)msg;
            //获取uri,过滤制定的资源
            URI uri=new URI(httpRequest.uri());
            ByteBuf content=null;
            if("/mb".equals(uri.getPath())){
                System.out.println("请求含有非路径上下文,不能理会....");
                //回复给浏览器的信息
              content= Unpooled.copiedBuffer("请求含有非路径上下文,不能理会....", CharsetUtil.UTF_8);
               // return;
            }
            else{
                //回复给浏览器的信息
                content= Unpooled.copiedBuffer("hello,我是服务器,你在干什么!!!", CharsetUtil.UTF_8);
            }
            //构造一个http的响应,即httpresponse
            FullHttpResponse response=new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK,content);
            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
            response.headers().set(HttpHeaderNames.ACCEPT_CHARSET,"utf-8");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());

            //构建好 response
            ctx.writeAndFlush(response);
        }
    }
}

4.测试结果

 过滤资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值