WebSocket实践

作者: Hughman | 来源:发表于2019-08-08 11:05 被阅读3次

    WebSocket

    1 WebSocket概述

    1)WebSocket是一种网络通信协议,是HTML5开始提供的一种在单个TCP连接上进行全双工通信的协议;是为了兼容现有浏览器的握手规范;

    2)是一种浏览器与服务器进行全双工通信的网络技术,属于应用层协议,基于TCP传输协议,并复用HTTP的握手通道;

    3)在 WebSocketAPI中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

    4)浏览器通过 JavaScript向服务器发出建立 WebSocket连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP连接直接交换数据。

    5)当获取 WebSocket连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

    2 WebSocket与HTTP协议

    1)HTTP协议只能由客户端发起通信,这种单向请求的特点,带来的问题是如果服务器有连续的状态变化,客户端获知非常麻烦,只能用轮询的方式,每隔一段时间,发出一个询问,了解服务器有没有新的信息,这种效率比较低,浪费资源;

    2)websocket是一个持久化的协议;而HTTP是非持久化协议;

    3)HTTP1.0生命周期是通过Request界定,一个Request一个Response,则请求就结束了;HTTP1.1中有一个keep-alive,在一个HTTP连接中,可以发送多个Request,接收多个Response,Response和Request对应的,且Response是被动的,不能主动发起;

    4)http是一个无状态协议;

    引用图1

    3 WebSocket特点

    3.1 优点

    1)服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种;

    2)支持双向通信,实时性更强;

    3)更好的二进制支持;

    4)较少的控制开销。连接创建后,ws客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不包含头部的情况下,服务端到客户端的包头只有2~10字节(取决于数据长度),客户端到服务端的话,需要加上额外的4字节的掩码。而HTTP协议每次通信都需要携带完整的头部。

    5)支持扩展。ws协议定义了扩展,用户可以扩展协议,或者事项自定义的子协议。(比如支持自定义压缩算法等)

    3.2 举例

    客户端发起:

    引用图2

    服务端回复:服务端返回内容如下,状态代码101表示协议切换。到此完成协议升级,后续的数据交互都按照新的协议来

    引用图3

    • Connection: Upgrade:表示要升级协议

    • Upgrade: websocket:表示要升级到websocket协议。

    • Sec-WebSocket-Version: 13:表示websocket的版本。如果服务端不支持该版本,需要返回一个Sec-WebSocket-Versionheader,里面包含服务端支持的版本号。

    • Sec-WebSocket-Key:与后面服务端响应首部的Sec-WebSocket-Accept是配套的,提供基本的防护,比如恶意的连接,或者无意的连接。

    4 WebSocket原理

    4.1 其他方式的被动性

    1)ajax轮询:让浏览器每隔几秒就发送一次请求,询问服务器是否有信息;


    引用叙述1

    2)long poll:类似于ajax轮询,采取阻塞模型(一直打电话,没收到对方回应就不挂电话),客户端发起连接后,如果没信息,就一直不返回Response给客户端,直到有消息才返回,然后客户端再次建立连接;

    引用叙述2

    3)websocket:只需要经过一次HTTP请求,就可以不断的互通消息;


    引用叙述3

    4.2 websocket的产生

    1)ajax轮询需要服务器有很快的处理速度和资源;long poll需要有很高的并发,及同时接待客户的能力;

    2)websocket在服务器完成协议升级后(HTTP->websocket),服务端就可以主动推送消息给客户端;

    3)只需要经过一次HTTP请求,就可以不断的互通消息;解决了服务器消耗资源以及同步延迟问题;

    5 常用属性

    5.1 @WebSocketEndpoint

    注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端。注解的值将被用于监听用户连接的终端访问URL地址。

    5.2 @onOpen

    打开一个新连接,即有新连接时,会调用被此注解的方法。

    5.3 @onClose

    关闭连接时调用。

    5.4 @onMessage

    当服务器接收到客户端发送的消息时所调用的方法。

    5.5 @PathParam

    接收 uri参数的,与@PathVariable功能差不多,可通过url获取对应值

    6 WebSocket 后端JAVA实现

    6.1 pom文件依赖

     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
            </dependency>
    
    依赖

    6.2 运行类

    1)添加注解:

    @EnableWebSocket

    2)添加Bean:

    @Bean
     public ServerEndpointExporter serverEndpointExporter() {
     return new ServerEndpointExporter();
     }
    
    @Bean

    6.3 WebSocket controller类

    1)注解:

    @ServerEndpoint(value = "/heartbeatMonitor/{userId}")
    @Component

    2)其他类注入方式:


    注入

    3)方法使用:

    @ServerEndpoint(value = "/websocket/{usernick}")为例

    1.  @OnOpen
    2.  public void onOpen(@PathParam(value = "usernick") String userNick,Session session) {
    3.  String message = "有新游客[" + userNick + "]加入聊天室!";
    4.  log.info(message);
    5.  WebSocketUtil.addSession(userNick, session);    
    6.  //此时可向所有的在线通知 某某某登录了聊天室 
    7.  WebSocketUtil.sendMessageForAll(message);
    8.  }
    
    10.  @OnClose
    11.  public void onClose(@PathParam(value = "usernick") String userNick,Session session) {
    12.  String message = "游客[" + userNick + "]退出聊天室!";
    13.  log.info(message);
    14.  WebSocketUtil.remoteSession(userNick);  
    15.  //此时可向所有的在线通知 某某某登录了聊天室 
    16.  WebSocketUtil.sendMessageForAll(message);
    17.  }
    
    19.  @OnMessage
    20.  public void OnMessage(@PathParam(value = "usernick") String userNick, String message) {
    21.  //类似群发
    22.  String info = "游客[" + userNick + "]:" + message;
    23.  log.info(info);
    24.  WebSocketUtil.sendMessageForAll(message);
    25.  }
    
    27.  @OnError
    28.  public void onError(Session session, Throwable throwable) {
    29.  log.error("异常:", throwable);
    30.  try {
    31.  session.close();
    32.  } catch (IOException e) {
    33.  e.printStackTrace();
    34.  }
    35.  throwable.printStackTrace();
    36.  }
    
    websocket方法

    6.4 测试

    http://coolaf.com/tool/chattest

    1)连接


    websocket open

    2)发送消息


    websocket onMessage

    相关文章

      网友评论

        本文标题:WebSocket实践

        本文链接:https://www.haomeiwen.com/subject/vjitjctx.html