基于Netty的websocket的简单介绍

1、websocket简介

「WebSocket」是一种在单个TCP连接上进行全双工通信的协议。

「WebSocket」使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在「WebSocket API」中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

TCP连接是一种可靠的、面向连接的网络通信协议。它通过三次握手建立连接,然后通过数据包的传输和确认来保证数据的可靠性和顺序性。

在建立TCP连接时,客户端首先向服务器发送一个SYN(同步)包,服务器收到后回复一个SYN+ACK(同步+确认)包,客户端再回复一个ACK(确认)包,完成了三次握手,建立了连接。在连接建立后,双方可以通过发送和接收数据包进行通信。

发送方将数据分割成小的数据包,并为每个数据包添加序列号。接收方接收到数据包后进行确认,并按照序列号将数据包重新组装成完整的数据。

「WebSocket」可以双向通讯,它可以完成客户端到服务端以及服务端到客户端的双向推送的通讯工具。

2、其他类似的产品

因为「WebSocket」可以数据的实时推送,所以常用用推送一些实时变化的数据。在我们业务场景中大多数实现的服务端到客户端的单向推送,其实现的方式还有很多种。

  • 客户端轮询,如间隔n秒发送http请求,以保证拉取准实时的数据

  • 长轮询,保持长时间的http连接,超时之后继续轮询。具有代表性的就是SSE,chatgpt就是基于SSE实现的

  • 长链接,也就是socket连接

前两种都是短连接基于http协议的的,其中长轮询主要是设置请求头:

Connection: keep-alive

3、数据推送存在问题

  • 短轮询存在很多无效的请求,拉取的数据的间隔不好掌握,拉取的数据未必是实时的

  • 长轮询的超时时间难以掌控,如果设置成永久保持,那么页面关闭或退出,连接依然有效,浪费链接资源。

  • SSE是基于长轮询的,实现了断线重连,超时、异常的回调等。但是多开页面,断线重新,都会产品不同的客户端,做到精准推送需要管理好不同的客户端,客户端的增多可能会造成服务端的OOM,这些都是考虑的重点

  • websocket则存在粘包、拆包的问题以及客户端的异常关闭等

其中netty解决websocket中常见的问题。

4、基于Netty解决socket的问题

Netty 中提供一系列解决socket的方案。

4.1 Socket服务端
public void run() {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {// 创建Socket服务端ServerBootstrap b = new ServerBootstrap();// bossGroup辅助客户端的tcp连接请求, workGroup负责与客户端之前的读写操作b.group(bossGroup, workerGroup)// 设置NIO类型的channel.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel channel) throws Exception {// ...}});// 配置完成,开始绑定server,通过调用sync同步方法阻塞直到绑定成功Channel channel = b.bind(port).sync().channel();// 对关闭通道进行监听channel.closeFuture().sync();} catch (InterruptedException e) {logger.error("webSocket server start error:" + e.getMessage());} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}
}

从样例代码中有几个关键的对象:

  • ServerBootstrap 这个是服务端的对象

  • NioServerSocketChannel 这个是服务端绑定的Channel类型

  • bind(port) 绑定服务端的端口

  • 使用双EventLoopGroup

4.2 Socket客户端
private void start() throws InterruptedException {EventLoopGroup eventLoopGroup = new NioEventLoopGroup();// 创建客户端Bootstrap bootstrap = new Bootstrap();// 设置NIO类型的channelbootstrap.channel(NioSocketChannel.class);bootstrap.option(ChannelOption.SO_KEEPALIVE, true);bootstrap.group(eventLoopGroup);bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel)throws Exception {// ...}});// 连接ChannelFuture future = bootstrap.connect(host, port).sync();if (future.isSuccess()) {logger.info("connect server success");}NioSocketChannel channel = future.channel();
}

样例中的关键对象:

  • Bootstrap 创建客户端的对象

  • NioSocketChannel 客户端绑定的channel类型

  • connect(host, port) 客户端是用来连接服务端的

  • 只有一个EventLoopGroup

5、Netty解决的Socket问题的类

5.1 IdleStateHandler

读写空闲处理器,一般用来写空闲来发送心跳检测消息

    /*** Creates a new instance firing {@link IdleStateEvent}s.** @param readerIdleTimeSeconds*        an {@link IdleStateEvent} whose state is {@link IdleState#READER_IDLE}*        will be triggered when no read was performed for the specified*        period of time.  Specify {@code 0} to disable.* @param writerIdleTimeSeconds*        an {@link IdleStateEvent} whose state is {@link IdleState#WRITER_IDLE}*        will be triggered when no write was performed for the specified*        period of time.  Specify {@code 0} to disable.* @param allIdleTimeSeconds*        an {@link IdleStateEvent} whose state is {@link IdleState#ALL_IDLE}*        will be triggered when neither read nor write was performed for*        the specified period of time.  Specify {@code 0} to disable.*/public IdleStateHandler(int readerIdleTimeSeconds,int writerIdleTimeSeconds,int allIdleTimeSeconds) {this(readerIdleTimeSeconds, writerIdleTimeSeconds, allIdleTimeSeconds, TimeUnit.SECONDS);}

对应的Handler处理

需要继承SimpleChannelInboundHandler 或实现 ChannelInboundHandler接口, 重写或实现userEventTriggered 方法。

例:

public class NettyClientHandler extends SimpleChannelInboundHandler<?> {//利用写空闲发送心跳检测消息@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof IdleStateEvent) {IdleStateEvent e = (IdleStateEvent) evt;switch (e.state()) {// 读空间case READER_IDLE// ...break;// 写空闲case WRITER_IDLE:// ...break;// 读写空闲	case ALL_IDLE:// ...break;default:break;}}}}
5.2 HttpServerCodec

Http请求解码器和Http响应的编码器合二为一。相当于HttpRequestDecoderHttpResponseEncoder 。用来处理Http请求的。

pipeline.addLast(new HttpServerCodec());
5.3 ChunkedWriteHandler

以快的方式写入,也就是大数据量的流式写入

pipeline.addLast(new ChunkedWriteHandler());
5.4 HttpObjectAggregator

聚合器,将一块块的数据聚合在一起,形成一条完整的数据

pipeline.addLast(new HttpObjectAggregator(64 * 1024));
5.3 拆包粘包解决方案
  • FixedLengthFrameDecoder 使用定长的报文来分包

  • DelimiterBasedFrameDecoder 添加特殊分隔符报文来分包

  • LineBasedFrameDecoder 数据未尾添加回车换行符来分包

  • LengthFieldBasedFrameDecoder 使用消息头和消息体来分包

  • StringDecoder 字符串解码器

  • StringEncoder 字符串编码器

  • ByteToMessageDecoder 如果想实现自己的半包解码器,实现该类

5.4 WebSocketServerProtocolHandler

订阅websocket的连接,也是webscoket的关键

pipeline.addLast(new WebSocketServerProtocolHandler("/ws"))

6、浏览器作为客户端

WebSocket一般的浏览器是直接支持的的。

let socket = new WebSocket('ws://localhost:8080/ws');
// 打开 连接
socket.addEventListener('open', function (event) {socket.send('Hello Server!');
});// 监听动态 数据
socket.addEventListener('message', function (event) {console.log('Message from server ', event.data);
});

浏览器作为客户端时,浏览器已经处理了粘包、拆包分析。不需要专门的处理,数据是frame的形式发送的,frame中包含了完整数据的标识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/7392.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

羊大师解析,鲜为人知的羊奶冷知识

羊大师解析&#xff0c;鲜为人知的羊奶冷知识 羊奶的脂肪球更小&#xff1a;相较于牛奶&#xff0c;羊奶中的脂肪球直径更小&#xff0c;这有助于其更快地被人体消化和吸收。 羊奶含有更多的中链脂肪酸&#xff1a;羊奶中含有较多的中链脂肪酸&#xff08;MCT&#xff09;&am…

5个好用AI绘画工具,让你秒变艺术家!

AI绘画现在可谓是相当火爆&#xff0c;各种AI绘画工具如雨后春笋般涌出。很多人想自己尝试用AI来创作&#xff0c;却不知道使用什么工具&#xff0c;今天就给大家分享5个好用AI绘画工具&#xff0c;有的只需一段文字便可生成一幅美轮美奂的大作&#xff0c;让你秒变艺术家&…

Spring Cloud Stream的作用和用法

Spring Cloud Stream是一个用于构建消息驱动型微服务的框架&#xff0c;它在Spring Cloud生态系统中扮演着关键角色。以下是关于Spring Cloud Stream的作用和用法的详细描述&#xff1a; 一、作用 简化消息中间件集成&#xff1a;Spring Cloud Stream旨在简化和统一消息中间件…

基于springboot实现的疫情网课管理系统

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

Implicit Diffusion Models for Continuous Super-Resolution

CVPR2023https://github.com/Ree1s/IDM问题引入&#xff1a; – LIIF方法可以实现任意分辨率的输出&#xff0c;但是因为是regression-based方法&#xff0c;所以得到的结果缺少细节&#xff0c;而生成的方法(gan-based,flow-based&#xff0c;diffusion-based等)可以生成细节&…

虚幻引擎中的投影技术主要用于创建多屏交互式内容和沉浸式显示环境

首先&#xff0c;在虚幻引擎&#xff08;UE4&#xff09;中&#xff0c;nDisplay插件是一个强大的工具&#xff0c;它允许开发者创建多屏投影系统。这种系统可以是由多个相邻的物理屏幕组成&#xff0c;例如Powerwall显示器&#xff0c;或者使用多个投影仪将3D环境投射到物理表…

oxford-iiit-pet 数据集

文章目录 项目说明数据集说明 oxford-iiit-pet 代码实现数据处理整理原始数据-分类划分 训练集和测试集 项目说明 数据集说明 oxford-iiit-pet 数据官方网站&#xff1a; https://www.robots.ox.ac.uk/~vgg/data/pets/ 下载 .torrent 文件&#xff0c;然后下载完整文件。 主要…

C# 继承和静态属性或方法

目录 继承&#xff1a; 静态属性和方法&#xff1a; 在子类中访问父类的静态属性和方法&#xff1a; 继承与静态属性或方法的关系&#xff1a; 注意&#xff1a; PS&#xff1a;如有错漏之处&#xff0c;敬请指正 在C#中&#xff0c;继承&#xff08;inheritance&#xf…

JavaScript基础(五)

三目运算符 用于判断并赋值 语法: 判断条件?条件成立执行语句:条件不成立执行语句; (条件&#xff1f;"true":"false";) 例: <script> var age prompt(请输入年龄) var name (age>18)?"已成年":"未成年禁止登录" a…

开源投票系统源码及搭建 在线投票活动创建系统的设计与开发

在当今数字化时代&#xff0c;在线投票活动已成为各类组织、企业和个人不可或缺的一部分。无论是选举、问卷调查、产品评选还是其他需要收集公众意见的场景&#xff0c;一个高效、稳定且易于使用的在线投票系统都至关重要。 分享一款基于开源投票系统源码的在线投票活动创建系…

uniapp从数组中删除重复项

在 UniApp&#xff08;或任何使用 JavaScript 的环境中&#xff09;从数组中删除重复项&#xff0c;你可以使用多种方法。以下是一些常见的方法&#xff1a; 1. 使用 filter() 和 indexOf() 你可以使用 Array.prototype.filter() 方法结合 Array.prototype.indexOf() 方法来创…

【网络知识】光猫、路由器 和 交换机 的作用和区别?

数字信号&#xff1a;是指自变量是离散的、因变量也是离散的信号&#xff0c;这种信号的自变量用整数表示&#xff0c;因变量用有限数字中的一个数字来表示。在计算机中&#xff0c;数字信号的大小常用有限位的二进制数表示。 模拟信号&#xff1a;模拟信号是指用连续变化的物…

偏微分方程算法之混合边界条件下的差分法

目录 一、研究目标 二、理论推导 三、算例实现 四、结论 一、研究目标 我们在前几节中介绍了Poisson方程的边值问题&#xff0c;接下来对椭圆型偏微分方程的混合边值问题进行探讨&#xff0c;研究对象为&#xff1a; 其中&#xff0c;为矩形区域&#xff0c;为上的连续函数…

巴东电子商务奖励标准!巴东县网红直播基地、电子商务示范企业奖励补贴

巴东电子商务奖励标准&#xff01;巴东县网红直播基地、电子商务示范企业奖励补贴的内容整理如下&#xff1a;奖励内容较多 查找想了解的奖励可按 CtrlF 然后输入关键词即可 巴东县电子商务发展专项资金支持对象 本项目奖补对象适用于在我县注册、纳税、从事电子商务的商贸类企…

ISIS的基本概念

1.ISIS概述 IS-IS是一种链路状态路由协议&#xff0c;IS-IS与OSPF在许多方面非常相似&#xff0c; 例如运行IS-IS协议的直连设备之间通过发送Hello报文发现彼此&#xff0c;然后建立邻接关系&#xff0c;并交互链路状态信息。 CLNS由以下三个部分组成&#xff1a; CLNP&#xf…

民航无人机证书的含金量

民航无人机证书&#xff0c;尤其是由中国民用航空局飞行标准司直接签发的CAAC无人机执照&#xff0c;具有很高的含金量。 这种驾照是由国家权威机构颁发的&#xff0c;具有很高的权威性&#xff0c;是合法操控无人机的重要依据。 持有CAAC无人机执照的从业人员可以从事无人机相…

VALSE 2024特邀报告内容解析|多模态视觉融合方法:是否存在性能极限?

2024年视觉与学习青年学者研讨会&#xff08;VALSE 2024&#xff09;于5月5日到7日在重庆悦来国际会议中心举行。本公众号将全方位地对会议的热点进行报道&#xff0c;方便广大读者跟踪和了解人工智能的前沿理论和技术。欢迎广大读者对文章进行关注、阅读和转发。文章是对报告人…

No space left on device

报错提示 [ERROR] Upload Local File hwzt-third-party-out.jar Failed [ERROR] java.lang.RuntimeException: cp: error writing : No space left on device [ERROR] com.alibabacloud.commons.ssh.sshj.SshjConnection.executeCustomCharset(SshjConnection.java:172) …

flask网站开发计划

我想写一个flask开发网站的合集文章&#xff0c;该网站主要是采集网络上的文章&#xff08;不同站点&#xff0c;用Python识别出正文内容&#xff09;&#xff0c;然后做成长图形式&#xff0c;发布到flask站点&#xff0c;并提供“下载”按钮&#xff0c;点击下载按钮&#xf…

文档打分系统部署操作手册

后台部署 java 运行环境的安装CentOS系统中安装Java Development Kit (JDK)-CSDN博客Redis的安装&#xff0c;配置文件与配置服务启动以及开机自动运行CentOS 7.9上安装Redis_centos7.9编译安装redis-CSDN博客Mysql的安装&#xff0c;配置文件与配置服务启动以及开机自动运行转…