IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Netty实现一个简单的Http服务器 -> 正文阅读

[网络协议]Netty实现一个简单的Http服务器

本篇文章参考了韩顺平老师的Netty视频教程,想要更细致的了解netty可以观看该教程进行学习。

1.什么是Netty

Netty 是一个广泛使用的 Java 网络编程框架投,它是基于NIO(Nonblocking I/O,非阻塞IO),开发的网络通信框架,对比于BIO(Blocking I/O,阻塞IO),他的并发性能得到了很大提高。理解Netty首先要说说java的I/O模型:java一共支持三种:NIO,BIO,AIO,下面分别介绍一下这三种IO模型

1.1 同步阻塞IO模型(BIO)

即同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就启动一个线程进行处理。如果当前连接没有需要处理的事件,线程将处于阻塞状态。其简易示意图为下图:

优点:实现简单,适用于连接数目比较小且固定的架构

缺点:这个连接不做任何事情会造成不必要的线程开销, 并且当并发数较大时,需要创建大量线程来处理连接,系统资源占用较大。

1.2 同步非阻塞IO模型(NIO)

服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求都会注册到多路复用器(selector)上,多路复用器轮询到连接有?I/O?请求就进行处理。 具体来说,NIO 基于Channel(通道)和 Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从Buffer写入到通道中。Selector(选择器)用于监听多个通道的事件(比如:连接请求,数据到达等),因此使用单个线程就可以监听多个客户端通道。其简易示意图如图所示。

这里需要注意的时Buffer和Channel之间的数据流向是双向的,也就是说,可以完成双向的读写操作。

优点:NIO 是可以做到用一个线程来处理多个操作的。比如有1000个请求,那么服务器可能只需要开启50或者100个线程就能进行处理,大大提高了系统的吞吐量?。

缺点:编程复杂,而且传统的NIO还存在很多的bug。

而Netty就是基于NIO实现的,并且在此基础上进行了很多优化,使得开发人员可以很方便的开发高可用的网络程序。?

1.3 异步非阻塞IO模型(AIO)

AIO 引入异步通道的概念,采用了 Proactor 模式,简化了程序编写,有效的请求才启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用,AIO 还没有广泛应用,这里不做详细说明。

2.Netty能做什么?

(1)作为分布式远程调用框架(RPC)的通信框架,如dubbo就是采用netty框架进行服务通信。

(2)实现一个Http服务器。

(3)实现一个即时聊天系统。

(4)...

3.Netty的整体架构

Netty的整体架构图

?简要说明:

流程:NioEventLoop实际上就是循环工作线程,可以直接理解为一个线程。则NioEventLoopGroup是一个线程池(一个工作组),里面有多个NioEventLoop。而boss Group和workGroup则代表承担不同工作的工作组,在这里可以理解为bossGroup主要负责监听端口和处理连接事件,而workGroup则负责处理IO操作或者其他业务。客服端连接会被bossGroup上NioEventLoop注册到一个工作线程(workgroup上的NioEventLoop),工作线程上selector会循环监听channel中的事件,如果有事件发生,需要处理,则调用ChannelPieline中的handler进行处理。没有事件发生,也不会发生阻塞,而是处理任务队列中的任务。
需要注意:

(1)bossGroup中有多个NioEventLoop线程,每个NioEventLoop绑定一个端口,也就是说,如果需要监听多个端口的话,bossGroup里面也会有多个NioEventLoop。

(2)每个绑定在NioEventLoop上的channel都由Selector管理。一个NioEventLoop的selector可以注册多个channel,也就是说多个Channel共享一个EventLoop。EventLoop的Selecctor对这些Channel进行轮询,查看是否有事件发生。

(3)一个NioEventLoop绑定了一个ChannelPipline链表(上面有多个处理器handler),ChannelPipline链表必须严格按照顺序执行的。(都在NioEventLoop这个线程上执行,保证了顺序执行,并且不被其他连接干扰)。

3.Netty实现简易http服务器

(1)编写Http服务器启动类

package com.it.netty.httpserver;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;


public class MyHttpServer {
    public static void main(String[] args) throws Exception{
        // boss工作组
        NioEventLoopGroup bossGroup = null;
        // worker工作组
        NioEventLoopGroup workerGroup = null;
        try {
            bossGroup = new NioEventLoopGroup();
            workerGroup = new NioEventLoopGroup();

            // 设置启动对象
            ServerBootstrap bootstrap = new ServerBootstrap();
            // 配置启动对象
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new MyChannelInitalizer());
            System.out.println("http 服务器已就绪");
            // 同步绑定端口
            ChannelFuture cf = bootstrap.bind(8000).sync();

            // 绑定监听关闭状态
            cf.channel().closeFuture().sync();
        } finally {
            // 关闭资源
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }

    }

}

(2)编写通道初始化类,将处理器(Handler)配置到通道(Channel)的管道(pipeline)中

package com.it.netty.httpserver;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

public class MyChannelInitalizer extends ChannelInitializer<SocketChannel> {

    protected void initChannel(SocketChannel ch) throws Exception {
        // 获取管道
        ChannelPipeline pipeline = ch.pipeline();

        // 设置编码解码处理器
        pipeline.addLast("MyHttpResponseEncoder", new HttpResponseEncoder());
        pipeline.addLast("MyHttpRequestDecoder", new HttpRequestDecoder());
        // 设置自定义处理器
        pipeline.addLast("MyHttpServerHandler", new MyHttpServerHandler());
    }
}

(3)自定义处理器,用于处理业务

package com.it.netty.httpserver;


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


public class MyHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {

    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        if (msg instanceof HttpRequest) {
            System.out.println("msg的真实类型" + msg.getClass());
            System.out.println("客服端地址" + ctx.channel().remoteAddress());
            // 回复信息给浏览器
            ByteBuf byteBuf = Unpooled.copiedBuffer("hello 我是自定义的Http服务器, 我正在服务.....", CharsetUtil.UTF_8);
            // 构造一个http响应体,即HttpResponse
            DefaultFullHttpResponse defaultFullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, byteBuf);
            // 设置响应头信息
            defaultFullHttpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain;charset=utf8");
            defaultFullHttpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, byteBuf.readableBytes());
            // 将响应体写入到通道中
            ctx.writeAndFlush(defaultFullHttpResponse);

        }
    }
}

启动服务,监听8000端口

?打开一个浏览器,访问该服务器,地址为http://localhost:8000

?一个简易的http服务器实现成功。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-12 17:57:52  更:2022-03-12 17:58:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:21:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码