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 服务

一、服务端代码

1.服务启动类

package com.example.netty.server;

import com.example.netty.server.init.NettyServerHttpInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * Description: Netty服务端
 *
 * @Author: zhx & moon hongxu_1234@163.com
 * @Date: 2021-11-14 23:31
 * @version: V1.0.0
 */
public class NettyServer {

    public static void main(String[] args) throws InterruptedException {

        //创建BossGroup 和 WorkerGroup
        /**
         * 1.创建两个线程组
         * 2.BossGroup 处理连接请求
         *   WorkerGroup 处理业务逻辑
         * 3.两个都是无限循环
         */
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            //创建服务端的启动对象 配置参数
            ServerBootstrap bootstrap = new ServerBootstrap();

            //使用链式编程进行设置
            /**
             * 1.设置两个线程组
             * 2.使用 NioSocketChannel 作为服务器的通道实现
             * 3.设置线程队列得到的连接数
             * 4.设置保持活动连接状态
             * 5.给我们的 WorkerGroup 的 EventLoop 对应的管道设置处理器
             */
            bootstrap.group(bossGroup,workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG,128)
                    .childOption(ChannelOption.SO_KEEPALIVE,true)
                    .childHandler(new NettyServerHttpInitializer());

            System.out.println("Server is Ready");

            //绑定一个端口并且同步 生成了一个 ChannelFuture 对象 启动服务
            ChannelFuture cf = bootstrap.bind(6668).sync();

            //对关闭通道进行侦听
            cf.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

2.管道初始化类

package com.example.netty.server.init;

import com.example.netty.server.handler.NettyServerHttpHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;

/**
 * Description: Netty Server 处理器初始化
 *
 * @Author: zhx & moon hongxu_1234@163.com
 * @Date: 2022-01-27 1:40
 * @version: V1.0.0
 */
public class NettyServerHttpInitializer extends ChannelInitializer<SocketChannel> {

    /**
     * 使用Netty自带的HTTP编解码器
     * @param ch
     * @throws Exception
     */
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast("httpDec",new HttpServerCodec()).addLast("httpHan",new NettyServerHttpHandler());
    }
}

3.处理器类

package com.example.netty.server.handler;

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;

/**
 * Description: Netty Server 处理器
 *
 * @Author: zhx & moon hongxu_1234@163.com
 * @Date: 2022-01-27 1:27
 * @version: V1.0.0
 */
public class NettyServerHttpHandler extends SimpleChannelInboundHandler<HttpObject> {

    /**
     * 读取客户端数据
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {

        //判断 msg 是否为 http request 请求
        if (msg instanceof HttpRequest){

            System.out.println("MSG Class " + msg.getClass());
            System.out.println("Client IP " + ctx.channel().remoteAddress());

            //回复信息给Http
            ByteBuf content = Unpooled.copiedBuffer("Hello,server is busing", CharsetUtil.UTF_8);

            //构造Http响应 http response
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK,content);
            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());

            //返回
            ctx.writeAndFlush(response);
        }
    }
}

4.启动服务,调用演示

在这里插入图片描述

5.如果出现6668不安全提示,可以将端口号修改为 > 8000 或修改浏览器配置

6.一次调用打印两次日志

查看浏览器控制台发现,回车发送请求,会默认查询站点图标
在这里插入图片描述

尝试在服务端过滤该请求,不做响应;处理器中插入以下代码段

String web_pic = "/favicon.ico";

HttpRequest httpRequest = (HttpRequest)msg;
URI uri = new URI(httpRequest.uri());
if (web_pic.equals(uri.getPath())){
    System.out.println("Request Ico,do not response...");
    return;
}

重启服务后,在次请求,查看结果如下
在这里插入图片描述

7.通道分析(服务端如何分配管道)

http 协议为无状态协议,通信完成即会断开连接,重复请求会重新分配管道
在这里插入图片描述

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-01-28 12:18:36  更:2022-01-28 12:21:04 
 
开发: 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 11:32:22-

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