分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > IT知识

Netty 开发HTTP服务端应用

发布时间:2023-09-06 01:26责任编辑:蔡小小关键词:暂无标签

HTTP协议:略

基于Netty的HTTP协议栈可以方便的进行异步非阻塞的HTTP服务器的开发。

当在浏览器中输入一个指向特定网页的URL时,浏览器就会生成一个HTTP请求,浏览器会与服务器建立TCP连接,当TCP可靠连接建立之后,浏览器会将生成的HTTP请求发送到服务器端。这时服务器程序接收到了信息将要去识别这个信息的内容,然后调用相应的服务程序,经过服务程序的分析和处理之后服务器端返回内容给浏览器。当服务器返回了内容给浏览器后,这时浏览器与服务器之间的数据交换完毕,这时TCP可靠连接就会断开。

下面是一个简单的例子,只处理GET请求:

html,css,js,jpg等资源位置如下

HttpServer

package com.luangeng.netty.http;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.codec.http.HttpObjectAggregator;import io.netty.handler.codec.http.HttpRequestDecoder;import io.netty.handler.codec.http.HttpResponseEncoder;import io.netty.handler.stream.ChunkedWriteHandler;/** * Created by LG on 2017/11/21. */public class HttpServer { ???public void run(final int port) throws Exception { ???????EventLoopGroup bossGroup = new NioEventLoopGroup(); ???????EventLoopGroup workerGroup = new NioEventLoopGroup(); ???????try { ???????????ServerBootstrap b = new ServerBootstrap(); ???????????b.group(bossGroup, workerGroup) ???????????????????.channel(NioServerSocketChannel.class) ???????????????????.childHandler(new ChannelInitializer<SocketChannel>() { ???????????????????????@Override ???????????????????????protected void initChannel(SocketChannel ch) ???????????????????????????????throws Exception { ???????????????????????????// HTTP请求消息解码器 ???????????????????????????ch.pipeline().addLast("http-decoder", new HttpRequestDecoder()); ???????????????????????????/* ????????????????????????????* HttpObjectAggregator解码器 ????????????????????????????* 将多个消息转换为单一的FullHttpRequest或FullHttpResponse对象 ????????????????????????????*/ ???????????????????????????ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(65536)); ???????????????????????????//HTTP响应编码器,对HTTP响应进行编码 ???????????????????????????ch.pipeline().addLast("http-encoder", new HttpResponseEncoder()); ???????????????????????????//ChunkedWriteHandler的主要作用是支持异步发送大的码流,但不占用过多的内存,防止JAVA内存溢出 ???????????????????????????ch.pipeline().addLast("http-chunked", ???????????????????????????????????new ChunkedWriteHandler()); ???????????????????????????ch.pipeline().addLast("httpServerHandler", new HttpServerHandler()); ???????????????????????} ???????????????????}); ???????????ChannelFuture future = b.bind("localhost", port).sync(); ???????????System.out.println("HTTP Server startup."); ???????????future.channel().closeFuture().sync(); ???????} catch (Exception e) { ???????????e.printStackTrace(); ???????} finally { ???????????bossGroup.shutdownGracefully(); ???????????workerGroup.shutdownGracefully(); ???????} ???} ???public static void main(String[] args) throws Exception { ???????int port = 8080; ???????new HttpServer().run(port); ???}}

---

HttpServerHandler

package com.luangeng.netty.http;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;import java.io.File;import java.io.FileInputStream;import java.net.URLDecoder;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;import static io.netty.handler.codec.http.HttpMethod.GET;import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;/** * Created by LG on 2017/11/21. */public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> { ???private static final String BASE_DIR = System.getProperty("user.dir") + "/src/main/java/com/luangeng/netty/http/i"; ???@Override ???protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { ???????//400 ???????if (!request.decoderResult().isSuccess()) { ???????????sendError(ctx, HttpResponseStatus.BAD_REQUEST); ???????????return; ???????} ???????//405 ???????if (request.method() != GET) { ???????????sendError(ctx, HttpResponseStatus.METHOD_NOT_ALLOWED); ???????????return; ???????} ???????//404 ???????String uri = request.uri(); ???????uri = URLDecoder.decode(uri, "UTF-8"); ???????uri = uri.replace(‘/‘, File.separatorChar); ???????File file = new File(BASE_DIR + uri); ???????if (!file.exists() || !file.isFile()) { ???????????sendError(ctx, HttpResponseStatus.NOT_FOUND); ???????????return; ???????} ???????FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.OK); ???????FileChannel channel = new FileInputStream(file).getChannel(); ???????ByteBuffer buffer = ByteBuffer.allocate(1024); ???????while (channel.read(buffer) != -1) { ???????????buffer.flip(); ???????????response.content().writeBytes(buffer); ???????????buffer.clear(); ???????} ???????channel.close(); ???????if(uri.endsWith(".css")){ ???????????response.headers().set(CONTENT_TYPE, "text/css; charset=UTF-8"); ???????}else { ???????????response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8"); ???????} ???????long fileLength = response.content().readableBytes(); ???????HttpUtil.setContentLength(response, fileLength); ???????ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); ???} ???@Override ???public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) ???????????throws Exception { ???????cause.printStackTrace(); ???????if (ctx.channel().isActive()) { ???????????sendError(ctx, HttpResponseStatus.INTERNAL_SERVER_ERROR); ???????} ???} ???private static void sendError(ChannelHandlerContext ctx, ?????????????????????????????????HttpResponseStatus status) { ???????FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, ???????????????status, Unpooled.copiedBuffer("Failure: " + status.toString() ???????????????+ "\r\n", CharsetUtil.UTF_8)); ???????response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8"); ???????ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); ???}}

---

hello.html

<!DOCTYPE html><html lang="en"><head> ???<meta charset="UTF-8"> ???<title>Hello</title> ???<link rel="stylesheet" type="text/css" href="/back.css"/> ???<script src="/jquery-1.11.3.min.js"></script></head><body><div style="background:#98bf21;height:100px;width:100px;position:absolute;"></div><p> ???一幅图像: ???<img src="/img1.jpg" width="128" height="128"/></p><p> ???一幅动画图像: ???<img id="img1" src="/eg_cute.gif" width="50" height="50"/></p><ul> ???<li>咖啡</li> ???<li>茶</li> ???<li>牛奶</li></ul></body><script type="text/javascript"> ???$(document).ready(function() { ???????timedCount(); ???}); ???function timedCount() { ???????var div=$("div"); ???????div.animate({height:‘300px‘,opacity:‘0.4‘},"slow"); ???????div.animate({width:‘300px‘,opacity:‘0.8‘},"slow"); ???????div.animate({height:‘100px‘,opacity:‘0.4‘},"slow"); ???????div.animate({width:‘100px‘,opacity:‘0.8‘},"slow"); ???????t=setTimeout("timedCount()",5000) ???}</script></html>

---

运行结果如下:

可见js,css,jpg等资源都可正常加载,

参考:Netty权威指南

end

Netty 开发HTTP服务端应用

原文地址:http://www.cnblogs.com/luangeng/p/7875710.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved