基于Netty的websocket的简单介绍

news/2024/5/21 2:44:58
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.mrgr.cn/p/75377300

相关文章

SOLIDWORKS参数化设计的作用

SOLIDWORKS参数化设计软件,主要解决加工制造型企业普遍存在的系列化产品设计周期长和出图效率低。重复工作多、人员工作强度大的问题。传统的设计模式下大规模定制型产品结构设计周期长,问题多,以及大量重复性工作让工程师疲于应对,这些严重阻碍了公司订单承接能力和技术创…

使用Docker安装MySQL5.7.36

拉取镜像并查看 docker pull mysql:5.7.36拉取成功后查看&#xff08;非必须&#xff09; docker images创建并设置宿主机 mysql 配置文件目录和数据文件目录 创建相关文件夹将容器中的mysql数据保存到本地&#xff0c;这样即使容器被删除&#xff0c;数据也不会丢失。 mkd…

【IDEA神器插件推荐】国产崛起!地表最强API测试插件

1.前言 在开发SpringBoot网站应用的过程中,前端后端会对接口进行请求测试。相信很多小伙伴都用过Postman,但是在IDE和Postman切换难免令人心烦。所以今天给大家带来一款IDEA内置的接口测试插件。 2.简介 根据插件的简介:Restful Fast Request 是一个类似于 Postman 的 Intel…

京东手势验证码-YOLO姿态识别+Bézier curve轨迹拟合

这次给老铁们带来的是京东手势验证码的识别。 目标网站&#xff1a;https://plogin.m.jd.com/mreg/index 验证码如下图: 当第一眼看到这个验证码的时候&#xff0c;就头大了&#xff0c;这玩意咋识别&#xff1f;&#xff1f;&#xff1f; 静下心来细想后的一个方案&#xf…

django显示网页步骤

显示网页步骤 小白的django学习笔记 2024/5/6 8:30 文章目录 显示网页步骤创建输入框&#xff08;文本、单选、多选&#xff09;效果如何在django中显示网页写函数配置地址运行&#xff0c;要选择这个工程名的&#xff0c;使用socket复制ip&#xff0c;后面在加上名字,成功&…

linux安装python3.8

一、卸载损坏的yum并安装 本来想直接下载安装python3.8,结果过程中损坏了yum,导致yum无法使用。 参考了【故障】6、yum不可用_yum命令无法使用-CSDN博客 1、删除python #删除现有的python rpm -qa|grep python|sudo xargs rpm -ev --allmatches --nodeps #强制删除已安装程…

2024好用的网页客服系统推荐?

2024好用的网页客服系统推荐&#xff1f;Zoho SalesIQ是一款强大的实时聊天工具&#xff0c;专为网站和在线商店设计。它提供了一套全面的功能&#xff0c;帮助企业实时解决客户问题&#xff0c;提高转化率和客户满意度。 实时监控 Zoho SalesIQ能够实时监控网站的访问者活动&…

Spring添加注解读取和存储对象

5大注解 Controller 控制器 Service 服务 Repository 仓库 Componet 组件 Configuration 配置 五大类注解的使用 //他们都是放在同一个目录下&#xff0c;不同的类中 只不过这里粘贴到一起//控制器 Controller public class UserController {public void SayHello(){System.ou…

智启蒸汽时代:数字孪生锅炉的革新之旅

数字孪生,就是通过数字技术为物理世界中的物体创建一个数字化的“双胞胎”。对于蒸汽工厂锅炉来说,数字孪生系统能够实时模拟锅炉的运行状态,预测可能出现的问题,并通过数据分析和智能决策为工人提供精准的操作建议。在飞速发展的工业4.0时代,数字孪生技术已经深入到我们生…

python数据分析——数据预处理

数据预处理 前言一、查看数据数据表的基本信息查看info&#xff08;&#xff09;示例 查看数据表的大小shape&#xff08;&#xff09;示例 数据格式的查看type()dtype&#xff08;&#xff09;dtypes&#xff08;&#xff09;示例一示例二 查看具体的数据分布describe()示例 二…

35岁自学编程有必要吗

在当今这个快速发展的数字化时代&#xff0c;学习编程已经不再局限于特定年龄层。对于35岁的人来说&#xff0c;自学编程不仅有必要&#xff0c;而且可能开启职业生涯的全新篇章。首先&#xff0c;编程技能是通往高科技行业的一把钥匙&#xff0c;能够为个人职业发展拓宽道路&a…

服务器(Linux系统)清除缓存

echo 1> /proc/sys/vm/drop_caches -- 清空系统缓存; cat /proc/29127/status -- 查看指定进程的状态信息;

Oracle Linux环境执行脚本

executeOracleSql.sh #!bin/bash# system:oracle的用户名;xxx:oracle的密码 # 后面追加要执行的sql脚本路径即可 sqlplus -s system/oracle@127.0.0.1:1521/xxx <<EOF @/home/mjtabu/basedb_init.sql exit; EOFecho "Please double check!!!";I have a dream…

js实现复制功能

/*** 复制* param {*} val 要复制的内容* returns*/ export const copyToClipboard async val > {try {// 使用现代 API 尝试复制if (navigator.clipboard && navigator.permissions) {await navigator.clipboard.writeText(val)return // 如果成功&#xff0c;直接…

kafka的名词解释

1.Replica(副本):在 Kafka 中,每个分区都有多个副本,用于提供数据的冗余备份和高可用性。副本可以分为两种类型:领导者副本(leader replica)和追随者副本(follower replica)。 领导者副本:每个分区都有一个领导者副本,它负责处理与客户端的所有读写请求,是分区的主…

vue3打开页面后文本框自动获得焦点

字符串写法 <script setup> import { ref, onMounted } from vue import ./index.cssconst input ref(null)onMounted(() > {input.value.focus() }) </script><template><div class"m-home-wrap"><input ref"input" />…

FPGA+炬力ARM实现VR视频播放器方案,3D眼镜显示

3D眼镜显示&#xff1a; FPGA炬力ARM方案&#xff0c;单个视频源信号&#xff0c;同时驱动两个LCD屏显示&#xff0c;实现3D 沉浸式播放 客户应用&#xff1a;VR视频播放器 主要功能&#xff1a; 1.支持多种格式视频文件播放 2.支持2D/3D 效果实时切换播放 3.支持TF卡/U盘文…

亚信安慧AntDB:解锁数智化的新时代

亚信安慧AntDB的融合实时的特性使得它在数据库领域独树一帜。传统的数据库系统往往只能追求数据的准确性和一致性&#xff0c;但在实际的业务场景中&#xff0c;这些特性并不能满足企业的需求。AntDB的出现打破了传统束缚&#xff0c;为企业带来了全新的数据处理方式&#xff0…

计算机基础-网络

一、网络设备 a.网卡(无线、有线) 物理层:提供物理地址,也叫MAC地址 b.网线(双绞线)、光缆 c.交换机、集线器 arp链路层:提供局域网内计算机与路由器之间建立端口映射,mac与IP的链路绑定 d.路由器 网络层:为局域网内计算机分配IP地址、防火墙、上网限制、网速控制登录 …

压力测试

压力测试压力测试 本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/18184743