【Netty】实战:基于Http的Web服务器
目录
一、实现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*/@Overrideprotected 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}.*/@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 添加自定义的handlerch.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();}}}
四、测试



我是马丁,如果你喜欢,麻烦点个赞~ 下期见~
相关文章:
【Netty】实战:基于Http的Web服务器
目录 一、实现ChannelHandler 二、实现ChannelInitializer 三、实现服务器启动程序 四、测试 本文来实现一个简单的Web服务器,当用户在浏览器访问Web服务器时,可以返回响应的内容给用户。很简单,就三步。 一、实现ChannelHandler pack…...
4K4D: Real-Time 4D View Synthesis at 4K Resolution 学习笔记
本文是学习4K4D的笔记记录 Project Page:https://zju3dv.github.io/4k4d/ 文章目录 1 Pipeline1.1 特征向量的计算1.2 几何建模1.3 外观建模⭐1) 球谐函数SH模型2) 图像融合技术 1.4 可微分深度剥离渲染 2 Train(loss)…...
2024年 Biomedical Signal Processing and Control 期刊投稿经验最新分享
期刊介绍 《Biomedical Signal Processing and Control 》期刊旨在为临床医学和生物科学中信号和图像的测量和分析研究提供一个跨学科的国际论坛。重点放在处理在临床诊断,患者监测和管理中使用的方法和设备的实际,应用为主导的研究的贡献。 生物医学信…...
【C++】关于类的public、protected 、private
public、protected、private是访问控制修饰符,决定了类成员的可访问性,特性如下: public: 可以被类内部和类外部直接访问 可以被派生类访问 protected: 可以被类内部访问 可以被派生类访问 不能被类的外部直接访问 p…...
使用 POST 方法与 JSON 格式进行 HTTP 请求的最佳实践
个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] 📱…...
学习笔记--Java基础核心知识
方法重载 请记住下面重载的条件 方法名称必须相同。参数列表必须不同(个数不同、或类型不同、参数类型排列顺序不同等)。方法的返回类型可以相同也可以不相同。仅仅返回类型不同不足以成为方法的重载。重载是发生在编译时的,因为编译器可以根…...
SAP学习笔记 - 开发01 - BAPI是什么?通过界面和ABAP代码来调用BAPI
BAPI作为SAP中的重要概念,在SAP系统的开发中几乎是必须的。 本章来学习一下BAPI 的直观印象,以及在ABAP代码中的调用。 目录 1, BAPI概述 1,从画面角度来直观体验一下BAPI 1-1,MM:購買依頼変更BAPI - …...
mysql笔记3(数据库、表和数据的基础操作)
文章目录 一、数据库的基础操作1. 显示所有的仓库(数据库)2. 创建数据库注意(命名规范): 3. 删除数据库4. 查看创建数据库的SQL5. 创建数据库时跟随字符编码6. 修改数据库的字符编码 二、表的基础操作1. 引入表的思维2. 引用数据库3. 查看该数据库下面的表4. 创建表…...
计算机毕业设计选题-基于python的企业人事管理系统【源码+文档+数据库】
💖🔥作者主页:毕设木哥 精彩专栏推荐订阅:在 下方专栏👇🏻👇🏻👇🏻👇🏻 实战项目 文章目录 实战项目 一、基于python的企业人事管理系…...
科研绘图系列:R语言折线图(linechart plots)
文章目录 介绍加载R包导入数据数据预处理画图组合图形介绍 在R语言中,折线图(Line Plot)是一种常用的数据可视化类型,用于展示数据随时间或有序类别变化的趋势。折线图通过连接数据点来形成一条或多条线,这些线条可以清晰地表示数据的变化方向、速度和模式。 加载R包 k…...
Opencv中的直方图(5)计算EMD距离的函数EMD()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 计算两个加权点配置之间的“最小工作量”距离。 该函数计算地球搬运工距离(Earth Mover’s Distance)和/或两个加权点配…...
KDD 2024 时空数据(Spatio-temporal) ADS论文总结
2024 KDD( ACM SIGKDD Conference on Knowledge Discovery and Data Mining, 知识发现和数据挖掘会议)在2024年8月25日-29日在西班牙巴塞罗那举行。 本文总结了KDD2024有关时空数据(Spatial-temporal) 的相关论文,如有疏漏,欢迎大…...
uniapp+vue3实现小程序和h5解压线上压缩包以及如何访问解压后的视频地址
安装jszip插件 npm install jszip 对应功能实现和逻辑处理: <script setup>import { onMounted, reactive, ref } from vueimport { onHide, onUnload } from dcloudio/uni-appimport JSZip from jsziplet videoSrc ref() // 视频地址// 创建JSZip实例con…...
探索 Zed 编辑器:速度与协作的巅峰之作
Zed 是一款备受瞩目的代码编辑器,专为现代开发者打造。本文将深入介绍 Zed 的独特优势,以及如何快速上手使用这款编辑器,助你在编程工作中大幅提升效率。 一:Zed 编辑器的优势 Zed 是近年来崭露头角的一款代码编辑器,迅速赢得了众多开发者的青睐。以下是 Zed 的几大核心优…...
文心快码前端工程师观点分享:人机协同新模式的探索之路(三)
本系列视频来自百度工程效能部的前端研发经理杨经纬,她在由开源中国主办的“AI编程革新研发效能”OSC源创会杭州站105期线下沙龙活动上,从一款文心快码(Baidu Comate)前端工程师的角度,分享了关于智能研发工具本身的研…...
Qt基础类03-直线类QLine
Qt基础类03-直线类QLine 摘要基本信息成员函数程序全貌QLine::QLine()QLine::QLine(const QPoint &p1, const QPoint &p2)QLine::QLine(int x1, int y1, int x2, int y2)QPoint QLine::p1() constQPoint QLine::p2() constint QLine::x1() constint QLine::x2() consti…...
集成电路学习:什么是ARM先进精简指令集计算机
ARM:先进精简指令集计算机 ARM先进精简指令集计算机(Advanced RISC Machine,简称ARM)是一种基于精简指令集计算机(RISC)原则的计算机处理器架构,由英国的ARM公司开发。这种架构以其低功耗和高性…...
设计模式-行为型模式-迭代器模式
1.迭代器模式的定义 迭代器模式提供一种对容器对象中的各个元素进行访问的方法,而不需要暴露该对象的内部细节; 在软件系统中,容器对象有两个职责:一是存储数据,二是遍历数据;从依赖性上看,前者…...
FRP代理(QUIC通信)实验
访问关系与TCP实验相同,配置不一样 服务端配置 客户端配置 通信数据...
项目依赖拉不下来卡着不动怎么办,node又不支持cnpm
如果你的项目依赖在拉取时卡住,可以尝试以下步骤来解决问题: 检查网络:确保你的网络连接稳定。如果可能,尝试使用 VPN 或更换网络。 使用镜像源: 对于 yarn,可以使用淘宝镜像: yarn confi…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...
boost::filesystem::path文件路径使用详解和示例
boost::filesystem::path 是 Boost 库中用于跨平台操作文件路径的类,封装了路径的拼接、分割、提取、判断等常用功能。下面是对它的使用详解,包括常用接口与完整示例。 1. 引入头文件与命名空间 #include <boost/filesystem.hpp> namespace fs b…...
C#最佳实践:为何优先使用as或is而非强制转换
C#最佳实践:为何优先使用as或is而非强制转换 在 C# 的编程世界里,类型转换是我们经常会遇到的操作。就像在现实生活中,我们可能需要把不同形状的物品重新整理归类一样,在代码里,我们也常常需要将一个数据类型转换为另…...
