文章目录

  • 简介
  • netty的HTTP支持
  • netty中使用HTTP的原理
    • 100 (Continue) Status
  • 为netty搭建HTTP服务器
  • 总结

简介

之前讲了那么多关于netty的文章,都是讲netty的底层原理和实现,各位小伙伴一定都在想了,看了这么多篇文章,netty到底能干啥呢?今天让我们来使用netty简简单单搭一个支持中文的服务器,展示一下netty的威力。

netty的HTTP支持

今天我们搭的服务器是支持HTTP1.1的服务器。在netty中搭建服务器就像是拼房子,找到合适的工具就可以事半功倍。那么要搭建HTTP的房子,netty提供了什么样的工具呢?

在讲解netty对HTTP的支持之前,我们先看一下HTTP的版本发展情况。

HTTP的全称是Hypertext Transfer Protocol,是在1989年World Wide Web发展起来之后出现的标准协议,用来在WWW上传输数据。HTTP/1.1是1997年在原始的HTTP协议基础上进行的补充和优化。

到了2015年,为了适应快速发送的web应用和现代浏览器的需求,发展出了新的HTTP/2协议,主要在手机浏览器、延时处理、图像处理和视频处理方面进行了优化。

基本上所有的现代浏览器都支持HTTP/2协议了,但是还有很多应用程序使用的是老的HTTP/1.1协议。netty为HTTP2和HTTP1提供了不同的支持包,对于HTTP1的支持包叫做netty-codec-http,对HTTP2支持的包叫做netty-codec-http2。

本文会讲解netty对HTTP1的支持,将会在后续的文章中继续HTTP2的介绍。

netty-codec-http提供了对HTTP的非常有用的一些封装。

首先是代表HTTP中传输对象的类HttpObject,这个类代表着传输中的所有对象。继承这个类的对象有两个非常重要的对象,分别是HttpMessage和HttpContent。

HttpMessage可能跟我想象的不太一样,它实际上只包含了两部分内容,分别是HttpVersion和HttpHeaders,但是并不包含任何内容。

public interface HttpMessage extends HttpObject {HttpVersion protocolVersion();HttpMessage setProtocolVersion(HttpVersion version);HttpHeaders headers();
}

这里HttpVersion只支持HTTP/1.0和HTTP/1.1协议。而HttpHeaders就是对HTTP请求中头对象的封装。

HttpMessage的子类是HttpRequest和HttpResponse,所以这两个类本身是不带请求内容的。

而具体请求的内容是在HttpContent中,HttpContent继承自ByteBufHolder,表示它中间可以带有ByteBuf的内容信息。

而HttpContent真正的实现类就是DefaultFullHttpRequest和DefaultFullHttpResponse,这两个内包含了HTTP头和HTTP请求响应内容信息。

那么问题来了,为什么要把HTTP头和HTTP内容分开呢?

这就涉及到HTTP1.1中消息传输中的压缩机制了。为了提升传输的效率,一般来说在传输的的过程中都会对象消息进行压缩,但是对于HTTP1.1来说,头部的内容是没办法压缩的,只能压缩content部分,所以需要区别对待。

netty中使用HTTP的原理

我们知道netty底层是客户端和服务器端构建通道,通过通道来传输ByteBuf消息。那么netty是怎么支持HTTP请求呢?

当客户端向服务器端发送HTTP请求之后,服务器端需要把接收到的数据使用解码器解码成为可以被应用程序使用的各种HttpObject对象,从而能够在应用程序中对其解析。

netty提供了HttpResponseEncoder和HttpRequestDecoder类,来对HTTP的消息进行编码和解码。

如果不想分别使用两个类来进行编码和解码,netty还提供了HttpServerCodec类来进行编码和解码工作。

这个类包含了HttpRequestDecoder和HttpResponseEncoder两部分的工作,可以同时用来进行编码和解码。

100 (Continue) Status

在HTTP中有一个独特的功能叫做,100 (Continue) Status,就是说client在不确定server端是否会接收请求的时候,可以先发送一个请求头,并在这个头上加一个"100-continue"字段,但是暂时还不发送请求body。直到接收到服务器端的响应之后再发送请求body。

为了处理这种请求,netty提供了一个HttpServerExpectContinueHandler对象,用来处理100 Status的情况。

当然,如果你的客户端没有这种请求,那么可以直接使用HttpObjectAggregator来将HttpMessage和HttpContent和合并成为FullHttpRequest或者FullHttpResponse。

为netty搭建HTTP服务器

有了上面的工作,我们就可以使用netty搭建http服务器了。最关键的一点就是在HttpRequestServerInitializer添加对应的codec和自定义handler。

    public void initChannel(SocketChannel ch) {ChannelPipeline p = ch.pipeline();p.addLast(new HttpServerCodec());p.addLast(new HttpServerExpectContinueHandler());p.addLast(new HttpRequestServerHandler());}

在自定义的handler中,我们需要实现一个功能,就是当收到客户端的请求时候,需要返回给客户端一段欢迎语。

首先将获得的HttpObject转换成为HttpRequest对象,然后根据请求对象构建一个DefaultFullHttpResponse对象,然后设置该response对象的头,最后将该对象写到channel中。

对应的关键代码如下:

 private static final byte[] CONTENT = "欢迎来到www.flydean.com!".getBytes(StandardCharsets.UTF_8);public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) {if (msg instanceof HttpRequest) {HttpRequest req = (HttpRequest) msg;boolean keepAlive = HttpUtil.isKeepAlive(req);FullHttpResponse response = new DefaultFullHttpResponse(req.protocolVersion(), OK,Unpooled.wrappedBuffer(CONTENT));response.headers()
//                    .set(CONTENT_TYPE, TEXT_PLAIN).set(CONTENT_TYPE, "text/plain;charset=utf-8").setInt(CONTENT_LENGTH, response.content().readableBytes());if (keepAlive) {if (!req.protocolVersion().isKeepAliveDefault()) {//设置header connection=keep-aliveresponse.headers().set(CONNECTION, KEEP_ALIVE);}} else {// 如果keepAlive是false,则设置header connection=closeresponse.headers().set(CONNECTION, CLOSE);}ChannelFuture f = ctx.write(response);if (!keepAlive) {f.addListener(ChannelFutureListener.CLOSE);}}}

上面的关键代码中CONTENT包含了中文字符串,我们使用getBytes将其转换成了UTF-8编码的byte数组。那么如果要想客户端能够正确识别UTF-8编码,需要在response的header中设置内容类型文件为:“text/plain;charset=utf-8”。

最后,使用下面的代码启动server:

 // server配置EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.option(ChannelOption.SO_BACKLOG, 1024);b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new HttpRequestServerInitializer());Channel ch = b.bind(PORT).sync().channel();log.info("请打开你的浏览器,访问 http://127.0.0.1:8000/");ch.closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}

总结

现在,使用你的浏览器访问你搭建的服务器地址,你就可以得到"欢迎来到www.flydean.com!"。 到此一个简单的netty服务器就完成了。

本文的例子可以参考:learn-netty4

本文已收录于 http://www.flydean.com/19-netty-http-client-request/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

netty系列之:轻轻松松搭个支持中文的服务器相关推荐

  1. 这个“1句话生成视频”AI爆火:支持中文输入,分辨率达到480×480,清华智源出品...

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 萧箫 发自 凹非寺 量子位 | 公众号 QbitAI 一周不到,AI ...

  2. Linux 服务器设置成支持中文

    Linux 服务器设置成支持中文 由于服务器默认是不支持中文的.所以一般需要单独设置一下. 检查本机已有的语言包 locale -a 默认是没有中文的,所以会显示: C C.UTF-8 POSIX e ...

  3. 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 如何 ?

    [读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 如何 ? 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...

  4. Linux下mysql支持中文,linux下mysql环境支持中文配置步骤

    sql脚本执行前加上: CREATE DATABASE IF NOT EXISTS mydatabase DEFAULT CHARSET utf8 COLLATE UTF8_GENERAL_CI; u ...

  5. netty系列之:netty架构概述

    文章目录 简介 netty架构图 丰富的Buffer数据机构 零拷贝 统一的API 事件驱动 其他优秀的特性 总结 简介 Netty为什么这么优秀,它在JDK本身的NIO基础上又做了什么改进呢?它的架 ...

  6. 配置中文_星球大战:战机中队配置需求公布 支持中文

    近日<星球大战>系列新作<星球大战:战机中队>公布,该作采用寒霜引擎打造,支持中文.游戏将于2020年10月3日发售,预购价格为238元,登陆Xbox One/PS4/PC(S ...

  7. java transferto_小六六学Netty系列之Java 零拷贝

    前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger种一棵树最好的时间是十年前,其次是现在 我知道很多人不玩qq了 ...

  8. IntelliJ IDEA 2020.1 正式发布,15 项重大特性、官方支持中文了! | 原力计划

    头图&作者 | YourBatman,CSDN博客专家 责编 | 唐小引 出品 | CSDN(ID:CSDNnews) 前言 千呼万唤始出来!自从官方在 2020-01-20 发布了其 202 ...

  9. netty系列之:自建客户端和HTTP服务器交互

    文章目录 简介 使用客户端构建请求 accept-encoding server解析HTTP请求 总结 简介 上一篇文章,我们搭建了一个支持中文的HTTP服务器,并且能够从浏览器访问,并获取到相应的结 ...

最新文章

  1. 高通创投在中国区的投资重点,目前主要聚焦在AI+5G、XR+5G、机器人/自动驾驶+5G、物联网+5G四个方面。
  2. 【奖】《密码信》破解者们,快来领奖啦!
  3. Java 8:对速度3.0.1“森林”流ORM的更深入了解
  4. SQLServer之函数简介 1
  5. java work set没有显示出来_eclipse里新建work set,将项目分组放在不同文件夹
  6. 大咖说中台 | 建设数据中台系列(五)——中台架构详解(下)
  7. 保存数组类型数据_「Java」基础12:什么叫数组?
  8. Android系统信息获取 之十四:获取WIFI热点相关信息
  9. A+B Problem(再升级)
  10. VS2017超有用秘钥(亲测)
  11. 《游戏设计、原型与开发——基于Unity与C#从构思到实现》学习笔记一
  12. 5G十大细分应用场景研究报告
  13. Intel/Nvidia双显卡笔记本用U盘安装ubuntu和Nvidia驱动
  14. 语音系统智能AI机器人AI源码营销机器人电销机器人智能电话机器人拨号机器人语音机器人空号识别FreeSWITCH呼叫中心中间ipbxIPBX科大识别阿里识别语音识别语音翻译
  15. Python分析上证指数历史数据,发现估值还不够低……
  16. 更改计算机账户类型,win10系统无法更改账户类型的两种解决方案
  17. 理财 股票 K线分析
  18. 【图解版】深入web请求过程
  19. 续:Windows Vista操作系统最新安全特性分析:改进和局限 (下)
  20. 协议确认机制TACK的通俗解析

热门文章

  1. 视音频编解码学习工程:JPEG分析器
  2. 缓冲区溢出漏洞攻击——Shellcode编写
  3. C++中IDispatch接口
  4. 深入理解程序执行原理
  5. 深入理解netfilter框架|经典PDF
  6. 除了负载均衡,Nginx还可以做很多,限流、缓存、黑白名单等
  7. RabbitMQ负载均衡(2)——HAProxy
  8. 面试官:Redis的事务满足原子性吗?
  9. 编写与优化 Go 代码(一)
  10. LiveVideoStackCon 2020北京站 | 参会指南