Spring框架SpringFrameworkJava 杂谈

WebSocket实践

2019-08-08  本文已影响3人  Hughman

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
上一篇下一篇

猜你喜欢

热点阅读