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

ops/2024/10/9 0:50:26/

目录

一、实现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();}}}

四、测试

https://i-blog.csdnimg.cn/direct/566b906a0ee3403eb1cbe3136de8a892.png" width="1200" />

https://i-blog.csdnimg.cn/direct/55d5f4a039f84447ae606b1836e0414b.png" width="1200" />

https://i-blog.csdnimg.cn/direct/118f4dfc5cef40889a9b364102903df0.png" width="1200" />

 


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


http://www.ppmy.cn/ops/105311.html

相关文章

万字长文:大模型从入门到实战

第1节 引言与基础知识 1. 什么是AI文案创作&#xff1f; 嘿&#xff0c;朋友们&#xff01;有没有觉得写文案就像是在给朋友写一封充满情感的长信&#xff1f;好吧&#xff0c;AI文案创作就是在这封长信中找个聪明的帮手&#xff0c;来个“AI写手”&#xff01;想象一下&…

前后端分离项目实战-通用管理系统搭建(前端Vue3+ElementPlus,后端Springboot+Mysql+Redis)第七篇:菜单和路由动态绑定

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

浅析JVM invokedynamic指令和Java Lambda语法|得物技术

一、导语 尽管近年来JDK的版本发布愈发敏捷&#xff0c;当前最新版本号已经20&#xff0c;但是日常使用中&#xff0c;JDK8还是占据了统治地位。 你发任你发&#xff0c;我用Java8&#xff1a;【Jetbrains】2023 开发者生态系统现状 - https://www.jetbrains.com/zh-cn/lp/dev…

【数论 状态机dp】2572. 无平方子集计数

本文涉及知识点 C动态规划 数论 质数、最大公约数、菲蜀定理 LeetCode 2572. 无平方子集计数 给你一个正整数数组 nums 。 如果数组 nums 的子集中的元素乘积是一个 无平方因子数 &#xff0c;则认为该子集是一个 无平方 子集。 无平方因子数 是无法被除 1 之外任何平方数整…

Docker通信全视角:原理、实践与技术洞察

一、引言 在云计算和微服务架构日益成熟的今天&#xff0c;Docker作为一种轻量级的容器化技术&#xff0c;已成为现代软件开发和部署的关键组件。Docker容器通过为应用程序提供隔离的运行环境&#xff0c;不仅显著提升了部署效率&#xff0c;而且增强了系统的可移植性和安全性。…

git中的分支是什么?分支有哪些好处?如何建立分支?

git中的分支是什么&#xff1f; 在Git中&#xff0c;分支是版本库中记录版本位置&#xff08;支线&#xff09;的一种方式。分支可以被视为一条时间线&#xff0c;每次提交都会在这条时间线上形成一个新的版本。通过分支&#xff0c;开发者可以在不影响主线&#xff08;通常是…

TS 学习(一)

如果我们在 ts 中写 不用运行就能在文件中报错 ts 是一种静态类型的检查 能将运行时出现的错误前置 一般不用 命令行编译 ts 转换成 js 将中文转码 tsc index&#xff08;.ts&#xff09; 输入命令生成 配置文件 能在中间进行 配置转换成 js 的哪个规范 es5 还是 6 和其它转…

Java12 Excel和Json文件解析

Excel文件解析&#xff1a; Excel文件解析(EasyExcel框架解析) Excel文件解析(Apache POl框架解析) &#xff08;1&#xff09;Excel文件对象创建&#xff1a;POI 《1》创建工作簿对象: XSSFWorkbook workbooknew XSSFWorkbook&#xff08;&#xff09;&#xff1b; 《2》创…