WebSocket

背景介绍

早期,很多网站为了实现推送技术,所用的技术都是轮询(也称为短轮询)。轮询是指浏览器每隔一段时间向服务器发送 HTTP 请求,然后服务器返回最新的数据给客户端。

常见的轮询方式分为轮询和长轮询,他们的区别如下图所示:

WebSocket_第1张图片

为了更加直观的感受轮询与短轮询之间的区别,我们来看一下具体代码:

WebSocket_第2张图片

短轮询的方式有一个明显的缺点,即浏览器需要不断的向服务器发出请求,然而 HTTP 请求与响应可能会包含较长的头部,其中真正有效的数据可能只是一小部分,所以这样会浪费很多的带宽资源。

在下棋游戏过程中轮询操作就会出现下图情况,

WebSocket_第3张图片

很明显,像这样的轮询操作,开销是比较大的,而且成本也比较高。如果轮询间隔时间太长,玩家1 落子之后,玩家2 就不能及时拿到结果,如果轮询间隔时间太短,虽然即时性得到改善,但是玩家2 会多次发送请求,这将会浪费更多的机器资源。

WebSocket简介

websocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。

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

接下来我们用一张图看一下 XHR Polling(短轮询)与 websocket 之间的区别。

WebSocket_第4张图片

websocket 优点

  1. 较少的控制开销,在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据报头部相对较小。
  2. 更强的实时性,由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于 HTTP 请求需要等待客户端发起请求,服务端才能响应,延迟明显更少。
  3. 保持连接状态,与 HTTP 不同的是,websocket 需要先创建连接,这就使得其成为一种有状态的协议(之后通信时可以省略部分状态信息)。
  4. 更好的二进制支持,websocket 定义了二进制帧,相对 HTTP 而言,可以更轻松的处理二进制内容。
  5. 可以支持扩展,websocket 定义了扩展,用户可以扩展协议、实现部分自定义的子协议。

WebSocket报文格式

WebSocket_第5张图片

websocket也是一个应用层协议,下层是基于TCP的。

FIN:标识是否结束

RSV:保留位,未来可能会用到,但是现在没有用

opcode:描述了当前 websocket 报文的类型,(文本帧、二进制帧、ping帧、pong帧...)

payload len:表示的是当前数据报携带的数据载荷的长度,这个字段本身就是一个变长的,一个 websocket 数据报能承载的载荷长度是非常非常长的。

payload data:实际报文要传输的数据载荷

WebSocket握手过程(建立连接的过程)

使用网页端,尝试和 服务器建立 websocket 连接。网页端首先给服务器发送一个 HTTP 请求,这个 HTTP 请求中会带有特殊的 header

Connection:Upgrade

Upgrade:Websocket

这两个 header 的作用就是告诉服务器,我要进行协议升级。

如果服务器支持 websocket,就会返回一个特殊的 HTTP 响应,这个响应的状态码是 101(切换协议)。然后客户端和服务器之间就开始使用 websocket 来进行通信了。

WebSocket示例

@Component
public class TestAPI extends TextWebSocketHandler {
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("连接成功");
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("收到信息:" + message.getPayload());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("连接异常");
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("连接关闭");
    }
}

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Autowired
    private TestAPI testAPI;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(testAPI, "/test");
        
    }

}

afterConnectionEstablished:WebSocket 建立连接之后执行

handleTextMessage:收到前端发送的信息之后执行,可以处理接收的信息

handleTransportError:传输过程中遇到错误时执行

afterConnectionClosed:连接关闭之后执行,可以释放一些不需要的资源

你可能感兴趣的:(websocket,网络协议,网络)