【Netty】实战:基于Http的Web服务器

news2024/9/27 12:17:05

目录

一、实现ChannelHandler 

二、实现ChannelInitializer

三、实现服务器启动程序

四、测试


本文来实现一个简单的Web服务器,当用户在浏览器访问Web服务器时,可以返回响应的内容给用户。很简单,就三步。

一、实现ChannelHandler 

package cn.md.netty.httpserver;

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

/**
 * * @Author: Martin
 * * @Date    2024/9/1 17:47
 * * @Description
 **/
public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    /**
     * Is called for each message of type {@link I}.
     *
     * @param ctx the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler}
     *            belongs to
     * @param msg the message to handle
     * @throws Exception is thrown if an error occurred
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
        // 打印Http请求
        printHttpRequest(msg);

        String uri = msg.uri();
        String resp;
        switch (uri) {
            case "/":
                resp = "hello world";
                break;
            case "/test":
                resp = "test";
                break;
            case "/hi":
                resp = "hello";
                break;
            default:
                resp = "404";
        }
        // 返回http格式响应
        returnHttpResp(ctx, resp);
    }

    private void returnHttpResp(ChannelHandlerContext ctx, String msg) {
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));

        response.headers().set(HttpHeaderNames.CONTENT_LENGTH,msg.length());

        ctx.writeAndFlush(response)
                .addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
    }

    private void printHttpRequest(FullHttpRequest msg) {
        String uri = msg.uri();
        HttpMethod method = msg.method();
        HttpVersion httpVersion = msg.protocolVersion();
        // 打印请求行
        System.out.println("uri:" + uri + " method:" + method + " httpVersion:" + httpVersion);

        HttpHeaders headers = msg.headers();
        for (String name : headers.names()) {
            System.out.println(name + ":" + headers.get(name));
        }

        System.out.println("");
        System.out.println(msg.content().toString(CharsetUtil.UTF_8));
    }
}

二、实现ChannelInitializer

package cn.md.netty.httpserver;

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

/**
 * * @Author: Martin
 * * @Date    2024/9/1 17:55
 * * @Description
 **/
public class HttpServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    /**
     * This method will be called once the {@link Channel} was registered. After the method returns this instance
     * will be removed from the {@link ChannelPipeline} of the {@link Channel}.
     *
     * @param ch the {@link Channel} which was registered.
     * @throws Exception is thrown if an error occurs. In that case it will be handled by
     *                   {@link #exceptionCaught(ChannelHandlerContext, Throwable)} which will by default close
     *                   the {@link Channel}.
     */
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        // 添加自定义的handler
        ch.pipeline().addLast("codec",new HttpServerCodec()) // 添加编解码器
                // 添加聚合器,聚合为一个完整的 FullHttpMessage
                .addLast("aggregator",new HttpObjectAggregator(1024*1024*10))
                .addLast("handler",new HttpServerHandler());
    }
}

三、实现服务器启动程序

package cn.md.netty.httpserver;

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

/**
 * * @Author: Martin
 * * @Date    2024/9/1 18:01
 * * @Description
 **/
public class HttpServer {

    public static void main(String[] args) {

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

        ServerBootstrap serverBootstrap = new ServerBootstrap();

        try {
            ChannelFuture channelFuture = serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new HttpServerChannelInitializer())
                    //服务器在处理客户端连接请求时的等待队列长度。
                    //当服务器接收到客户端的连接请求时,如果服务器正在处理其他连接或者处于忙碌状态,新的连接请求将被放入等待队列中。
                    .option(ChannelOption.SO_BACKLOG, 128)
                    //底层套接字级别设置的选项,由操作系统的 TCP/IP 协议栈实现保活机制。
                    //当开启后,在一定时间没有数据传输时,操作系统自动发送保活探测报文来检测连接是否仍然有效。
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .bind(8888)
                    .sync();


            channelFuture.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }

    }

}

四、测试

 


我是马丁,如果你喜欢,麻烦点个赞~ 下期见~

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

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

相关文章

Spring之拦截器(HandlerInterceptor)

前言 在web开发中&#xff0c;拦截器是经常用到的功能&#xff0c;用于拦截请求进行预处理和后处理&#xff0c;一般用于以下场景&#xff1a; 日志记录&#xff0c;可以记录请求信息的日志&#xff0c;以便进行信息监控、信息统计、计算PV&#xff08;Page View&#xff09;等…

C++ 继承(二)

目录 1. 实现一个不能被继承的类 2. 友元与继承 3.继承与静态成员 4.多继承及其菱形继承问题 (1). 继承模型 (2). 虚继承 (2.1)虚继承解决数据冗余和二义性的原理 (3). 多继承中指针偏移问题 (4). IO库中的菱形虚拟继承 5. 继承和组合 1. 实现一个不能被继承的类 方法1…

内蒙古众壹集团:引领蒙东财税服务行业,成就企业发展新高度

内蒙古众壹企业管理集团有限公司自2019年成立以来&#xff0c;凭借卓越的服务和专业的团队&#xff0c;迅速成长为蒙东地区财税服务行业的先锋企业。 公司在成立初期&#xff0c;通过加盟慧算账平台&#xff0c;快速进入市场&#xff0c;并设立了多个分公司&#xff0c;逐步扩展…

Daily2:字体描边

有一个小的需求,需要对字体进行描边,一开始理解错了需求,以为要对字体镂空处理,然后尝试了许多做错了许多 后来发现是一个简单的描边处理,直接chatgpt就可以得出来一个简单的实现代码, class BorderTextView JvmOverloads constructor(context: Context, attrs: AttributeSet?…

读懂以太坊源码(3)-详细解析genesis.json

要想搞懂以太坊的源代码逻辑&#xff0c;必须要了解以太坊创世区块配置文件(genesis.json)的结构&#xff0c;以及每个配置参数的意义&#xff0c;创世配置文件&#xff0c;主要作用是设置链的ID&#xff0c;指定以太坊网络中硬分叉发生的区块高度&#xff0c;以及初始ETH数量的…

【系统分析师】-软件测试

目录 1、测试的类型 1.1、动态测试 1.1.1、黑盒法 1.1.2、白盒法 1.1.3、灰盒法 1.2、静态测试 2、测试阶段 2.1、单元测试 2.2、集成测试 2.3、确认测试 2.4、系统测试 3、性能测试 3.1、性能测试的目的 3.2、性能测试的类型 3.3、性能测试的步骤 5、测试设计…

【操作系统存储篇】Linux文件基本操作

目录 一、Linux目录 二、Linux文件的常用操作 三、Linux文件类型 一、Linux目录 Linux有很多目录&#xff0c;Linux一切皆是文件&#xff0c;包括进程、设备等。 相对路径&#xff1a;相对于当前的操作目录&#xff0c;文件位于哪个目录。 绝对路径 &#xff1a;从根目录开…

面对AI时代快车,你没必要跟车赛跑,而是应该先去考个驾照!

在当今人工智能领域&#xff0c;代码生成和编辑工具成为了开发者们手中的利器。昨天&#xff0c;零一万物公司再次展示了他们在开源社区中的领导地位&#xff0c;开源了 Yi-Coder 系列编程助手模型&#xff0c;这一举措不仅标志着该公司继今年5月开源Yi-1.5系列模型后的又一重大…

智能提醒助理系列-服务号静默登录

本系列文章记录“智能提醒助理”wx公众号 建设历程&#xff0c;记录实践经验、巩固知识点、锻炼总结能力。 本文介绍&#xff0c;如何让用户进入公众号之后就锁定用户&#xff0c;使用既注册&#xff0c;进入既可使用功能&#xff0c;去掉繁琐的登录认证流程。 一、需求出发点 …

告别单调,Xmind思维导图之后还有这三款神器,让学习工作更愉快

这年头信息量爆炸&#xff0c;我们得想办法把事情想清楚、把活儿排排好、学点新玩意儿。思维导图这东西&#xff0c;因为它画出来一目了然&#xff0c;用起来也简单&#xff0c;所以特别受学生们和上班的人的欢迎。在这么多画思维导图的软件里&#xff0c;Xmind因为功能全、界面…

02【SQL sever 2005数据库安装教程】

一、安装须知 1.安装数据库版本&#xff1a;SQL sever 2005 2.适用系统&#xff08;目前发现&#xff09;&#xff1a;Windows server 2008 R2 3.安装程序目录&#xff1a;SQL2005\SQL Server x64\Servers\setup.exe 二、安装步骤 1&#xff0e;双击setup.exe&#xff0c;以…

c++编程(25)——unordered_map模拟实现

欢迎来到博主的专栏&#xff1a;c编程 博主ID&#xff1a;代码小豪 文章目录 unorder_map的底层insert迭代器成员访问函数operatoroperator-\- unordered_map是STL中的关联式容器之一&#xff0c;与常规的map有两点不同 &#xff08;1&#xff09;unordered是无序的意思&#x…

AI与我同创诗:尝试让ai(智谱清言)参与我的诗创活动

ai伴学越久&#xff0c;契合度愈高&#xff0c;“泛滥”之诗情&#xff0c;幸得学伴共雕琢。让ai伴学久了&#xff0c;不知觉的&#xff0c;写诗也让ai帮衬了。此文收录“我共ai”的自创文稿&#xff0c;亦可作“ai诗集”。&#x1f60b; (笔记模板由python脚本于2024年09月03日…

企业微信中嵌套的h5应用调用微信扫码功能

企业微信官方文档 1.登录企业微信后台,管理员可操作,打开应用配置应用可信域名(必须配置,否则无法调用jsapi,可信域名必须有ICP备案且在管理端验证域名归属) 配置部署后的前台域名地址 配置可信域名,部署后的服务器域名(需备案认证) 当域名权限不够时需下载文件效验,将文件放…

网站开发:HTML + CSS - CSS选择器

1. 前言 CSS&#xff08;Cascading Style Sheets&#xff0c;层叠样式表&#xff09;是一种用于控制 HTML 文档样式和布局的语言。它为 Web 页面提供了许多功能&#xff0c;使开发者能够创建美观且功能丰富的用户界面。 提供了丰富的功能来控制网页的外观和布局&#xff0c;增…

掌握SQLAlchemy:Python数据库的魔法师

文章目录 掌握SQLAlchemy&#xff1a;Python数据库的魔法师背景&#xff1a;为什么选择SQLAlchemy&#xff1f;SQLAlchemy是什么&#xff1f;如何安装SQLAlchemy&#xff1f;五个简单的库函数使用方法1. 创建引擎2. 定义模型3. 创建会话4. 添加数据5. 查询数据 场景应用1. 多表…

大模型构建合作性的Agent,多代理框架MetaGpt

大模型构建合作性的Agent,多代理框架MetaGpt 前言 MetaGPT 框架将标准的操作程序(SOP)与基于大模型的多智能体相结合,使用标准操作程序来编码提示,确保协调结构化和模块化输出。 MetaGPT 允许 Agent 在类似流水线的范式中扮演多中角色,通过结构化的 Agent 协作和强化领…

Android Studio 加载多个FLutter项目

按顺序操作即可 选择工程 选择Modules, 导入 module 选中创建module 选择要导入的目录&#xff0c;只选择主目录&#xff0c;下面的文件不要选 添加完成&#xff0c;点击ok后&#xff0c;会进行导入 最终导入成功

三星称霸全球市场,但它在中国市场再受打击,将进一步收缩业务

韩国媒体报道指三星已计划进一步收缩中国业务&#xff0c;将中国的销售和生产部门人员减少一部分&#xff0c;其中销售人员计划减少8%左右&#xff0c;显示出它在中国市场继续面临打击&#xff0c;对于这家在全球市场领先地位仍然稳固的企业来说&#xff0c;它在中国市场无疑又…

OpenCV结构分析与形状描述符(8)点集凸包计算函数convexHull()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 查找一个点集的凸包。 函数 cv::convexHull 使用斯克拉斯基算法&#xff08;Sklansky’s algorithm&#xff09;来查找一个二维点集的凸包&#…