Netty实现Http服务器案例

news2024/9/22 23:27:06

功能:

Netty服务器在6668端口监听,浏览器发出请求"http://localhost:6668"

服务器可以恢复消息给浏览器:“hello,我是服务器”,并对特定请求资源进行过滤

目的:

Netty可以做服务器端开发,并且理解handle实例和客户端及其请求的关系.

服务端代码(Server):

package com.liubujun.netty.http;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;

import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @Author: liubujun
 * @Date: 2023/2/11 15:06
 */


public class TestServer {

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

        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            //创建服务器端的启动对象,配置参数
            ServerBootstrap serverBootstrap = new ServerBootstrap();

            serverBootstrap.group(bossGroup,workerGroup)//设置两个线程组
                    .channel(NioServerSocketChannel.class) //使用nioSocketChannel作为服务器的通道实现
                    .childHandler(new TestServerInitalizer());

            //绑定一个端口并且同步,生成了一个ChannelFuture对象
            //启动服务器(并绑定端口)
            ChannelFuture cf = serverBootstrap.bind(8080).sync();
            //对关联通道进行监听
            cf.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

ServerInitalizer

public class TestServerInitalizer extends ChannelInitializer<SocketChannel> {


    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        //向管道加入处理器

        //得到管道
        ChannelPipeline pipeline = ch.pipeline();

        //加入一个netty 提供的HttpServerCodec
        //1.HttpServerCodec是netty提供的处理http的编-解码器
        pipeline.addLast("MyHttpServerCodec",new HttpServerCodec());
        //2.增加一个自定义的handler
        pipeline.addLast("MyTestHttpServerHandler",new TestHttpServerHandler());


    }
}

HttpServerHandler:

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

/**
 * @Author: liubujun
 * @Date: 2023/2/11 15:07
 */

/**
 * 说明:
 * 1. SimpleChannelInboundHandler 是 ChannelInboundHandlerAdapter
 * 2 HttpObject客户端和服务端相互通讯的数据被封装成HttpObject
 */
public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {


    //channelRead0 读取客户端数据
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {

        //判断msg是不是httpRequest请求
        if (msg != null){
            System.out.println("msg 类型="+msg.getClass());
            System.out.println("客户端地址"+ctx.channel().remoteAddress());

            //回复信息给浏览器
            ByteBuf content = Unpooled.copiedBuffer("hello,我是服务器", CharsetUtil.UTF_8);

            //构造一个http响应,即httpresponse
            DefaultFullHttpResponse 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());

            //将构建好的response返回
            ctx.writeAndFlush(response);


        }
    }
}

启动服务端,浏览器输入:http://localhost:8080/,得到服务端响应数据

但是服务端控制台却输出了如下请求:

我们只请求了一次,但是浏览器却发出了2次请求,并且对这两个请求都做了响应。

那么如何对这个网站图标进行过滤,使服务器对其不做响应呢?

可以在我们的服务端Handle加上如下代码:

            HttpRequest httpRequest = (HttpRequest)msg;
            URI uri = new URI(httpRequest.uri());
            if ("/favicon.ico".equals(uri.getPath())){
                System.out.println("请求了favicon.ico,不做响应");
                return;
            }

完整版HttpServerHandler代码如下:

package com.liubujun.netty.http;

import com.sun.jndi.toolkit.url.Uri;
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;

/**
 * @Author: liubujun
 * @Date: 2023/2/11 15:07
 */

/**
 * 说明:
 * 1. SimpleChannelInboundHandler 是 ChannelInboundHandlerAdapter
 * 2 HttpObject客户端和服务端相互通讯的数据被封装成HttpObject
 */
public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {


    //channelRead0 读取客户端数据
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {

        //判断msg是不是httpRequest请求
        if (msg != null){


            System.out.println("msg 类型="+msg.getClass());
            System.out.println("客户端地址"+ctx.channel().remoteAddress());

            HttpRequest httpRequest = (HttpRequest)msg;
            URI uri = new URI(httpRequest.uri());
            if ("/favicon.ico".equals(uri.getPath())){
                System.out.println("请求了favicon.ico,不做响应");
                return;
            }

            //回复信息给浏览器
            ByteBuf content = Unpooled.copiedBuffer("hello,我是服务器", CharsetUtil.UTF_16);

            //构造一个http响应,即httpresponse
            DefaultFullHttpResponse 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());

            //将构建好的response返回
            ctx.writeAndFlush(response);


        }
    }
}

再次重新请求发现:已经成功拦截。

注意:

http协议不是一个长连接

每个请求对应的handle和pineline是独立的,不会共享。

对此,可以请求2次并且打印出其hash值进行比对

第一次请求:

第二次请求:

发现连续2次请求所打印的hash值都不一样。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/341443.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

家政服务小程序实战教程07-轮播图组件

小程序中首页一般显示轮播图的功能&#xff0c;点击轮播图会跳转到具体的一篇文章或者是产品&#xff0c;本篇我们就介绍一下轮播图功能的开发 01 设计数据源 我们轮播图组件需要两个字段&#xff0c;一个是展示的图片&#xff0c;一个是跳转页面传入的参数。打开数据源&…

JAVA集合专题5 ——ArrayDeque + BlockingQueue

目录ArrayDeque的特点BlockingQueue什么是BlockingQueue?什么叫阻塞队列?阻塞队列的应用场景是什么?BlockingQueue的阻塞方法是什么?BlockingQueue的四类方法codecode2ArrayDeque的特点 ArrayDeque是Deque接口子实现ArrayDeque数据结构可以表示为: 队列、双端队列、栈Arra…

【MFC】工具条(16)

创建工具条的基本步骤是&#xff1a; 1.创建工具条资源。 2.构建一个CToolBar对象。 3.调用CToolBar::Create函数创建工具条窗口。 4.调用CToolBar::LoadToolBar载入工具条资源。 使用工具条 打开资源视图&#xff0c;可视化创建或者修改工具条&#xff1a; 其中ID项一般与菜…

【计组】硬盘--《深入浅出计算机组成原理》(十二)

目录 一、机械硬盘 二、SSD硬盘 &#xff08;一&#xff09;SSD硬盘的读写原理 1、SLC、MLC、TLC 和 QLC 2、P/E 擦写问题 &#xff08;二&#xff09;SSD 读写的生命周期 &#xff08;三&#xff09;磨损均衡、TRIM 和写入放大效应 1、FTL 和磨损均衡 2、TRIM 指令的…

vueday01-脚手架安装详细

一、vue脚手架安装命令npm i -g vue/cli 或 yarn global add vue/cli安装上面的工具&#xff0c;安装后运行 vue --version &#xff0c;如果看到版本号&#xff0c;说明安装成功或 vue -V工具安装好之后&#xff0c;就可以安装带有webpack配置的vue项目了。创建项目之前&#…

用队列实现栈VS用栈实现队列

之前我们就讲过队列&#xff0c;栈的基础知识&#xff0c;笔者之前有过详细的介绍&#xff0c;感兴趣的可以根据笔者的个人主页进行查找&#xff1a;https://blog.csdn.net/weixin_64308540/?typelately225. 用队列实现栈请你仅使用两个队列实现一个后入先出&#xff08;LIFO&…

加入bing体验chatGPT大军中来吧,它来了!

1 第一步&#xff1a;加入候选名单 1、首先需要加入候选名单 https://www.microsoft.com/zh-cn/edge?formMA13FJ 2、下载最新的Edge浏览器、androd、iOS都有试用版本&#xff08;可以看到iOS加护当前已满&#xff09; 这里我下载的是dev版本&#xff0c;Canary版本由于是…

50. Pow(x, n)

50. Pow(x, n) 一、题目描述&#xff1a; 实现 pow(x, n) &#xff0c;即计算 x 的整数 n 次幂函数&#xff08;即&#xff0c;xn &#xff09;。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n 10 输出&#xff1a;1024.00000 示例 2&#xff1a; 输入&#xff1a;x 2…

决策树分类算法(一)(信息熵,信息增益,基尼指数计算)

目录一、信息量二、信息熵三、信息增益四、基尼指数五、代码&#xff1a;信息熵&#xff0c;信息增益&#xff0c;基尼指数计算&#xff08;splitInfo.py&#xff09;例子&#xff1a; 一、信息量 : I(x)log⁡21p−log⁡2pI(x)\log_{2}{\frac{1}{p}}-\log_{2}{p}I(x)log2​p1…

傻白探索Chiplet,Modular Routing Design for Chiplet-based Systems(十一)

阅读了Modular Routing Design for Chiplet-based Systems这篇论文&#xff0c;是关于多chiplet通信的&#xff0c;个人感觉核心贡献在于实现了 deadlock-freedom in multi-chiplet system&#xff0c;而不仅仅是考虑单个intra-chiplet的局部NoC可以通信&#xff0c;具体的一些…

如何判断两架飞机在汇聚飞行?(如何计算两架飞机的航向夹角?)内含程序源码

ok&#xff0c;在开始一切之前&#xff0c;让我先猜一猜&#xff0c;你是不是想百度“二维平面下如何计算两个移动物体的航向夹角&#xff1f;”如果是&#xff0c;那就请继续往下看。 首先&#xff0c;我们要明确一个概念&#xff1a;航向角≠航向夹角&#xff01;&#xff0…

微信小程序图书馆座位预约管理系统

开发工具&#xff1a;IDEA、微信小程序服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7前端技术&#xff1a;vue、uniapp服务端技术&#xff1a;springbootmybatis本系统分微信小程序和管理后台两部分&#xff0c;项目采用…

家政服务小程序实战教程05-集成腾讯地图

我们在用户注册数据源部分设计了一个地图字段&#xff0c;地图字段在生成页面的时候对应着地图定位组件 要调用地图定位组件&#xff0c;需要先创建API&#xff0c;点击新建API 选择腾讯地图 创建API的时候需要输入API key 进入到腾讯位置服务里申请Key 首先需要创建一个应用 创…

Go 全栈博客实战项目 gin-vue-blog

Go 全栈博客 gin-vue-blog写在前面博客介绍在线预览项目介绍技术介绍目录结构环境介绍线上环境开发环境VsCode 插件快速开始拉取项目前的准备 (Windows)方式一&#xff1a;Docker Compose 一键运行方式二&#xff1a;常规运行项目部署总结鸣谢后续计划写在前面 这个项目其实已经…

Dubbo和Zookeeper集成

分布式理论 什么是分布式系统&#xff1f; 在《分布式系统原理与范型》一书中有如下定义&#xff1a;“分布式系统是若干独立计算机的集合&#xff0c;这些计算机对于用户来说就像单个相关系统”&#xff1b; 分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调…

分享111个助理类简历模板,总有一款适合您

分享111个助理类简历模板&#xff0c;总有一款适合您 111个助理类简历模板下载链接&#xff1a;https://pan.baidu.com/s/1JafYuLPQMmq37K4V0wiqWA?pwd8y54 提取码&#xff1a;8y54 Python采集代码下载链接&#xff1a;https://wwgn.lanzoul.com/iKGwb0kye3wj 设计师助理…

浅析SCSI协议(1)基本介绍

概述 SCSI即小型计算机接口&#xff08;Small Computer System Interface&#xff09;&#xff0c;指的是一个庞大协议体系&#xff0c;到目前为止经历了SCSI-1/SCSI-2/SCSI-3变迁。SCSI协议定义了一套不同设备&#xff08;磁盘、磁带、处理器、光设备、网络设备等&#xff09…

C/C++工业数据分析与文件信息管理系统[2023-02-12]

C/C工业数据分析与文件信息管理系统[2023-02-12] 程序设计基础A课程设计 工业数据分析与文件信息管理系统 题目背景 智能制造是以工业生产数据分析、自动化技术为基础&#xff0c;具有信息深度自感知、智慧优化自决策、精准控制自执行等功能&#xff0c;使制造活动达到安全…

[golang gin框架] 2.Gin HTML模板渲染以及模板语法,自定义模板函数,静态文件服务

一.Gin HTML 模板渲染全部模板放在一个目录里面的配置方法首先在项目根目录新建 templates 文件夹&#xff0c;然后在文件夹中新建 对应的index.html<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta http…

图像处理-边缘检测-文献阅读笔记

[1]李华琛. 基于opencv图像边缘检测技术[J]. 数字技术与应用, 2016(11):2. 高斯滤波有效抑制噪声&#xff1b;原理&#xff1a;识别图像中亮度改变较为明显的点&#xff0c;本质是采用不同的算子进行边缘检测并进行修整。算子&#xff1a;Laplacian 算子、Scharr 算子、Canny 算…