百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Netty WebSocket 协议(netty websocket protobuf)

ccwgpt 2024-10-27 08:48 43 浏览 0 评论

1. 前言

上一节,我们主要讲解了 Http 协议,本节我们来讲解 Netty 支持的另外一个 WebSocket 协议,WebSocket 是 HTML5 开始支持的全双工协议。

在真实的开发当中,其实 WebSocket 使用非常的广泛,特别是在目前前端技术越来越完善的情况下,很多应用都是基于前端技术去实现,比如:APP、小程序等主流应用,前端的技术完全可以开发出类似原生技术一样的产品,并且开发效率上比原生更加的快、用户体验更好。
这些应用涉及通信、聊天、推送等业务,则可以使用 WebSocket 来实现,因此,WebSocket 已经是目前非常主流的浏览器和服务端建立长连接的通信技术。

WebSocket 协议架构图如下所示:

2. 学习目的

Netty 虽然可以开发客户端和服务端的应用,但是 Netty 和 WebSocket 结合则是另外一个不同的应用方向。

应用方向一: 纯后端的应用,比如:框架、中间件通信等,则完全可以使用 Netty 来开发客户端和服务端,并且双方通过 TCP 协议来进行通信。

应用方向二: 前端(浏览器)和服务端之间通信,并且想实现类似长连接的效果,那么 WebSocket 和 Netty 则是主流,并且这部分的应用场景非常的广泛和运用非常的多。

因此,我们在学习完本章内容之后,我们就可以掌握这类的需求的开发(比如:聊天、消息推送),自己可以尝试去开发一款小程序在线聊天系统。

当真实的开发当中,也许很多人直接使用 Spring 封装的 WebSocket 或者其它第三方的框架(比如:netty-socketio)去实现。本节我们主要讲解原生 Netty 来开发 WebSocket 协议格式的数据请求,毕竟会用和知道知其所以然还是有区别的。

3. WebSocket 的 API

创建 WebSocket 对象,第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。

var Socket = new WebSocket(url, [protocol] );

WebSocket 事件

事件

事件处理程序

描述

open

Socket.onopen

连接建立时触发

message

Socket.onmessage

客户端接收服务端数据时触发

error

Socket.onerror

通信发生错误时触发

close

Socket.onclose

连接关闭时触发

4. 环境搭建

本节,我们主要开发一个 Demo,主要功能如下:

  1. 前端页面(html)启动的时候,连接 WebSocket 服务端;
  2. 服务端往前端每隔 5s 推送一条消息。

环境搭建步骤:

  1. 创建一个 Maven 项目;
  2. 导入 Netty 坐标。

实例:

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.6.Final</version>
</dependency>

5. 代码实现

5.1. Netty 主启动类

public class MyWebSocketServer {
    public static void main(String[] args) throws Exception{
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup);
            serverBootstrap.channel(NioServerSocketChannel.class);
            serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline pipeline = ch.pipeline();

                    //因为基于http协议,使用http的编码和解码器
                    pipeline.addLast(new HttpServerCodec());

                    //是以块方式写,添加ChunkedWriteHandler处理器
                    pipeline.addLast(new ChunkedWriteHandler());
                    
                    //http数据在传输过程中是分段, HttpObjectAggregator ,就是可以将多个段聚合
                    pipeline.addLast(new HttpObjectAggregator(8192));
                    
                    //将 http协议升级为 ws协议 , 保持长连接
                    pipeline.addLast(new WebSocketServerProtocolHandler("/hello2"));
                    
                    //自定义的handler ,处理业务逻辑
                    pipeline.addLast(new MyWebSocketHandler());
                }
            });

            //启动服务器
            ChannelFuture channelFuture = serverBootstrap.bind(7000).sync();
            channelFuture.channel().closeFuture().sync();

        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

代码说明:

  1. WebSocket 比 TCP 和 Http 协议都稍微复杂一点,它其实是 TCP 和 Http 协议的结合,首先是连接之前发送的是 Http 协议请求,但是新增 Http 所没有的附加头信息 Upgrade: WebSocket 表明是一个申请协议升级的 Http 请求。其次,真正建立连接之后,其实底层是 TCP 协议长连接;
  2. HttpServerCodec 将请求和应答消息解码为 HTTP 消息;
  3. ChunkedWriteHandler 向客户端发送 HTML5 文件;
  4. http 数据在传输过程中是分段,当浏览器发送大量数据时,就会发出多次 http 请求, HttpObjectAggregator 可以将 HTTP 消息的多个部分合成一条完整的 HTTP 消息;
  5. WebSocketServerProtocolHandler 定义了 WebSocket 的对外暴露地址。

5.2 WebSocket 业务类

public class MyWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>{
    private SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //1.获取Channel通道
        final Channel channel=ctx.channel();
        
        //2.创建一个定时线程池
        ScheduledExecutorService ses=Executors.newScheduledThreadPool(1);
        //3.一秒钟之后只需,并且每隔5秒往浏览器发送数据
        ses.scheduleWithFixedDelay(new Runnable() {
            public void run() {
                String sendTime=format.format(new Date());
                channel.writeAndFlush(new TextWebSocketFrame("推送时间=" + sendTime));
            }
        },1,5, TimeUnit.SECONDS);
    }

    //接受浏览器消息
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {

        System.out.println("收到消息 " + msg.text());
    }

    //当web客户端连接后,触发方法
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
		
    }

    //当web客户端断开后,触发方法
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {

    }
}

代码说明:

其实 WebSocket 对于的 Handler 跟我们普通业务的 Handler 没有什么区别,这里主要使用定时线程池定时往浏览器推送消息,这个是传统的 Http+Ajax 请求无法实现的逆向推送效果。

5.3. 前端代码

function WebSocketTest() {
    if ("WebSocket" in window) {
        var ws = new WebSocket("ws://localhost:7000/hello2");
        
        //发送数据
        ws.onopen = function() {
            ws.send("发送数据");
        };

        //接受数据
        ws.onmessage = function(evt) {
            var received_msg = evt.data;
            console.log(">>>"+received_msg)
        };

        //监听连接关闭
        ws.onclose = function() {
            alert("连接已关闭...");
        };
    } else {
        alert("您的浏览器不支持 WebSocket!");
    }
}

5.4 测试效果

浏览器控制台每隔 5s 钟就能收到服务端推送过来的消息,如下图所示:

6. 小结

  1. 我们需要了解 WebSocket 的应用方向,主要是前端和服务端建立长连接通信;
  2. 掌握 WebSocket 几个事件监听方法,open ()、message ()、error ()、close ();
  3. 掌握 Netty 编写的服务端写法,主要是几个类 HttpServerCodec、ChunkedWriteHandler、HttpObjectAggregator、WebSocketServerProtocolHandler,Handler 业务跟普通业务没啥区别

相关推荐

RACI矩阵:项目管理中的角色与责任分配利器

作者:赵小燕RACI矩阵RACI矩阵是项目管理中的一种重要工具,旨在明确团队在各个任务中的角色和职责。通过将每个角色划分为负责人、最终责任人、咨询人和知情人四种类型,RACI矩阵确保每个人都清楚自己...

在弱矩阵组织中,如何做好项目管理工作?「慕哲制图」

慕哲出品必属精品系列在弱矩阵组织中,如何做好项目管理工作?【慕哲制图】-------------------------------慕哲制图系列0:一图掌握项目、项目集、项目组合、P2、商业分析和NP...

Scrum模式:每日站会(Daily Scrum)

定义每日站会(DailyScrum)是一个Scrum团队在进行Sprint期间的日常会议。这个会议的主要目的是为了应对Sprint计划中的不断变化,确保团队能够有效应对挑战并达成Sprint目标。为...

大家都在谈论的敏捷开发&amp;Scrum,到底是什么?

敏捷开发作为一种开发模式,近年来深受研发团队欢迎,与瀑布式开发相比,敏捷开发更轻量,灵活性更高,在当下多变环境下,越来越多团队选择敏捷开发。什么是敏捷?敏捷是一种在不确定和变化的环境中,通过创造和响应...

敏捷与Scrum是什么?(scrum敏捷开发是什么)

敏捷是一种思维模式和哲学,它描述了敏捷宣言中的一系列原则。另一方面,Scrum是一个框架,规定了实现这种思维方式的角色,事件,工件和规则/指南。换句话说,敏捷是思维方式,Scrum是规定实施敏捷哲学的...

敏捷项目管理与敏捷:Scrum流程图一览

敏捷开发中的Scrum流程通常可以用一个简单的流程图来表示,以便更清晰地展示Scrum框架的各个阶段和活动。以下是一个常见的Scrum流程图示例:这个流程图涵盖了Scrum框架的主要阶段和活动,其中包...

一张图掌握项目生命周期模型及Scrum框架

Mockito 的最佳实践(mock方法)

记得以前面试的时候,面试官问我,平常开发过程中自己会不会测试?我回答当然会呀,自己写的代码怎么不测呢。现在想想我好像误会他的意思了,他应该是想问我关于单元测试,集成测试以及背后相关的知识,然而当时说到...

EffectiveJava-5-枚举和注解(java枚举的作用与好处)

用enum代替int常量1.int枚举:引入枚举前,一般是声明一组具名的int常量,每个常量代表一个类型成员,这种方法叫做int枚举模式。int枚举模式是类型不安全的,例如下面两组常量:性别和动物种...

Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!

Maven简介Maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行”。Maven是一个跨平台的项目管理工具。主要服务于基于Java平台的项目构建、依赖管理和项目信息管理。仔...

Java单元测试框架PowerMock学习(java单元测试是什么意思)

前言高德的技术大佬在谈论方法论时说到:“复杂的问题要简单化,简单的问题要深入化。”这句话让我感触颇深,这何尝不是一套编写代码的方法——把一个复杂逻辑拆分为许多简单逻辑,然后把每一个简单逻辑进行深入实现...

Spring框架基础知识-第六节内容(Spring高级话题)

Spring高级话题SpringAware基本概念Spring的依赖注入的最大亮点是你所有的Bean对Spring容器的存在是没有意识的。但是在实际的项目中,你的Bean必须要意识到Spring容器...

Java单元测试浅析(JUnit+Mockito)

作者:京东物流秦彪1.什么是单元测试(1)单元测试环节:测试过程按照阶段划分分为:单元测试、集成测试、系统测试、验收测试等。相关含义如下:1)单元测试:针对计算机程序模块进行输出正确性检验工作...

揭秘Java代码背后的质检双侠:JUnit与Mockito!

你有没有发现,现在我们用的手机App、逛的网站,甚至各种智能设备,功能越来越复杂,但用起来却越来越顺畅,很少遇到那种崩溃、卡顿的闹心事儿?这背后可不是程序员一拍脑袋写完代码就完事儿了!他们需要一套严谨...

单元测试框架哪家强?Junit来帮忙!

大家好,在前面的文章中,给大家介绍了以注解和XML的方式分别实现IOC和依赖注入。并且我们定义了一个测试类,通过测试类来获取到了容器中的Bean,具体的测试类定义如下:@Testpublicvoid...

取消回复欢迎 发表评论: