WebSocket基础

发布于 2023-05-04  2.98k 次阅读


1. WebSocket的产生背景

传统的web应用最广泛的是http网络协议,它是半双工网络通信协议,面对比如聊天、数据的实时展示、客服咨询等场景它有明显的弊端

HTTP协议:它是一种无状态、无连接、单向的应用层协议。主要采用请求/响应方式,通信请求只能由客户端发起,服务端对请求做出应答处理

采用Http通信协议最明显的弊端就是它无法实现服务器主动向客户端发起消息,对于需要服务器向客户端推送数据的应用场景,http协议做不到,但它有一种替代方案(AJAX轮询)

AJAX轮询:大部分Web应用程序使用HTTP协议实现类似于服务器推送功能时,都使用轮询的方式,但轮询的效率极低,非常浪费资源(需要不停的连接和请求)

因为HTTP协议的弊端,诞生了WebSocket协议这个更加优秀的特定场景解决方案

2. WebSocket协议

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器于服务器之间的全双工(full-duplex)通信 -- 允许服务器主动发送信息给客户端

WebSocket是一种持久协议,http是非持久协议

WebSocket协议包括两个部分:

  1. 握手:握手是基于http协议的,握手之后会对协议升级到websocket
  2. 数据传输:客户端可以发信息给服务端,服务端也可以发消息给客户端

① 客户端握手信息:

GET ws://localhost/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-key: xxxxxxxx
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Version: 13

② 来自服务器的握手信息:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: xxxxxxxx
Sec-WebSocket-Extensions: permessage-deflate

握手信息字段说明:

头名称
说明
Connection:Upgrade
标识该HTTP请求是一个协议升级请求
Upgrade:WebSocket
协议升级为WebSocket协议
Sec-WebSocket-Version: 13
客户端支持WebSocket的版本
Sec-WebSocket-key:
客户端采用base64编码的24位随机字符串序列,服务器接收客户端的HTTP协议升级的证明,要求服务端响应一个对应加密的Sec-WebSocket-Accept头信息作为应答
Sec-WebSocket-Extensions
协议拓展类型

3. WebSocket两端实现

3.1 客户端(浏览器)实现

实现WebSocket的Web浏览器将通过WebSocket对象公开所有必需的客户端功能

HTML5版本支持WebSocket协议进行全双工通信,支持Html5的浏览器才能使用WebSocket

创建WebSocket对象:

var ws = new WebSocket(url);
  • URL格式说明:ws://ip地址:端口号/资源名称

WebSocket的相关事件:

事件
事件处理程序
描述
open
websocket对象.onopen
连接建立时触发
message
websocket对象.onmessage
客户端接收服务端数据时触发
error
websocket对象.onerror
通信发生错误时触发
close
websocket对象.onclose
连接关闭时触发

WebSocket方法:

方法
描述
send()
使用连接发送数据

3.2 服务端实现(原生java方式)

Tomcat的7.0.5版本开始支持WebSocket,并且实现了Java WebSocket规范(JSR356)

    Java WebSocket应用由一 系列的WebSocketEndpoint组成,Endpoint是一个java对象,代表WebSocket链接的一端,对于服务端,我们可以是为处理具体WebSocket消息提供接口,就像Servlet之与http请求一样

可以通过两种方式定义Endponint:

  • 编程式:即继承类javax.websocket.Endpoint并实现其方法
  • 注解式:即定义一个POJO,并添加@ServerEndpoint

    Endpoint实例在WebSocket握手时创建,并在客户端与服务端连接过程中有效,最后在链接关闭时结束。在Endpoint接口中明确定义与其生命周期相关的方法,规范实现者确保生命周期的各个阶段调用实例的相关方法

生命周期方法如下:

方法
含义描述
onClose
当会话关闭时调用
onOpen
当开启一个新的会话时调用,该方法是客户端与服务端握手成功之后调用的方法
onError
当连接过程中异常时调用

服务端如何接收客户端发送的数据??

    编程式通过Session添加MessageHandler消息处理器来接收消息,当采用注解方式写Endpoint时,我们还可以通过@onMessage注解指定接收消息的方法

服务端如何推送数据给客户端??

    发送消息则由RemoteEndpoint完成,其实例由Session维护,根据使用情况,我们可以通过Seesion.getBasicRemote获取同步消息发送的实例,然后调用其sendxxx()方法就可以发送消息,还可以通过Session.getAsynncRemote获取异步消息发送实例

服务端代码演示:原生java注解方式

import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;

@ServerEndpoint("/myWs")
@Component
public class WsServerEndpoint {

        //连接成功
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("连接成功");
    }

    //连接关闭
    @OnClose
    public void onClose(Session session) {
        System.out.println("连接关闭");
    }

    //接收到消息
    @OnMessage
    public String onMsg(String text) throws IOException {
        return "servet 发送:" + text;
    }
}

 


路漫漫其修远兮,吾将上下而求索