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>() {
@Override
protected void initChannel(SocketChannel channel) throws Exception</