websocket原理和应用入门

栏目: Html5 · 发布时间: 5年前

内容简介:WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

原理

WebSocket是一种在单个TCP连接上进行全双工通信的协议。

WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。

在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

http协议中有keep-alive,只是把多个HTTP请求合并到一个tcp连接里进行传输, Websocket 是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范,也就是说它是HTTP协议上的一种补充。

websocket原理和应用入门

Websocket协议

HTTP协议中,HTTP的生命周期通过 Request 来界定,一个 Request对应 一个 Response,客户端发起一个Request,在收到Response之后,一次HTTP请求生命周期结束。而且必须客户端先发送一个Request,服务端才能给客户端发送Response,服务器端属于被动的,不能主动发起。WebSocket的基于长连接,可以双向通信,生命周期如下:

websocket原理和应用入门

有如下特点:

(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是 ws (如果加密,则为 wss ),服务器网址就是 URL。

WebSocket借用HTTP协议来完成首次握手,随后使用WebSocket进行通信。

HTTP握手请求如下:

GET /chat HTTP/1.1

Host:server.example.com

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==

Sec-WebSocket-Protocol: chat, superchat

Sec-WebSocket-Version: 13

Origin:example.com

Upgrade: websocket Connection: Upgrade 表示协议升级为websocket协议。

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== 客户端也就是浏览器或者其他终端随机生成一组16位的随机base64编码的串

Sec-WebSocket-Protocol: chat, superchat 使用协议

Sec-WebSocket-Version: 13 当前使用协议的版本号

握手返回如下:

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

Sec-WebSocket-Protocol: chat

状态码和描述 101 Switching Protocols表示协议切换成功

Upgrade: websocket Connection: Upgrade 表示协议升级成功为websocket 复制代码

Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key

Sec-WebSocket-Protocol 则是表示最终使用的协议

前端代码:

var ws = new WebSocket(" wss://echo.websocket.org ");

ws.onopen = function(evt) {

console.log("Connection open ...");

ws.send("Hello WebSockets!");

};

ws.onmessage = function(evt) {

console.log( "Received Message: " + evt.data);

ws.close();

};

ws.onclose = function(evt) {

console.log("Connection closed.");

};

运行代码

不支持WebSocket

不支持WebSocket的场景有:

  1. 浏览器不支持
  2. Web容器不支持,如tomcat7以前的版本不支持WebSocket
  3. 防火墙不允许
  4. Nginx没有开启WebSocket支持

基于 SockJS 的 WebSocket

在不支持WebSocket的情况下,也可以很简单地实现WebSocket的功能的,方法就是使用 SockJS。它会优先选择WebSocket进行连接,但是当服务器或客户端不支持WebSocket时,会自动在 XHR流、XDR流、iFrame事件源、iFrame HTML文件、XHR轮询、XDR轮询、iFrame XHR轮询、JSONP轮询 这几个方案中择优进行连接。

服务端

在启动WebSocket的配置中,你需要做的所有事情就是加上 withSockJS()

@Override

public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {

// withSockJS 声明启用支持 sockJS

webSocketHandlerRegistry.addHandler(marcoHandler(), "/echo").withSockJS();

客户端

在客户端需要引入SockJS库,然后把 new WebSocket(url); 替换成 new SockJS(url);

SockJS类和WebSocket类是兼容的,所以可以直接替换

<script type="text/javascript" src="/resources/js/sockjs-1.0.0.min.js"></script>

var sock = new SockJS(url);

应用

以下是一个基于spring、sockjs的一个样例

  1. 引入依赖
    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId></dependency>复制代码
  2. 添加配置
    @Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) {复制代码
    registry        .addEndpoint("/websocket/tracker")        .setAllowedOrigins("*")        .withSockJS();复制代码
    } @Override public void configureMessageBroker(MessageBrokerRegistry config) {复制代码
    config.enableSimpleBroker("/topic", "/user");        config.setUserDestinationPrefix("/user");        config.setApplicationDestinationPrefixes("/app");复制代码
    }} 复制代码

    1)@EnableWebSocketMessageBroker注解用于开启使用STOMP协议来传输基于代理(MessageBroker)的消息,这时候控制器(controller)开始支持@MessageMapping,就像是使用@requestMapping一样。

    2).addEndpoint("/websocket/tracker") 注册一个 Stomp 端点,客户端连接服务端是使用;.setAllowedOrigins("*")表示允许跨域;.withSockJS()表示指定使用SockJS协议。SockJs是一个WebSocket的通信js库,Spring对这个js库进行了后台的自动支持,如果使用它不需要进行过多配置。

    3)config.enableSimpleBroker("/topic", "/user") 启用一个简单的message broker并配置一个或多个前缀来过滤针对代理的目的地,客户端订阅这个地址,服务端可以向改地址发送消息;

    config.setApplicationDestinationPrefixes("/app");

  3. 提供接口
    @MessageMapping("/hello") @SendTo("/topic/greetings") public Greeting greeting(HelloMessage message) throws Exception {        System.out.println("收到:" + message.toString() + "消息");        return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"); }复制代码

    1)@MessageMapping用于设置URL映射地址,浏览器向服务器发起请求,需要通过该地址,客户端发送消息时,需要访问/app/hello。

    2)@SendTo("/topic/greetings") 设置目的地,服务器想客户端发送消息,这里的目的地是站在服务端的角度对客户端而言。客户端也需要设置相同的地址,而且必须使用/topic前戳,前面也已经讲述。

  4. 发送消息
    SimpMessagingTemplate.convertAndSendToUser(String user, String destination, Object payload)复制代码
    SimpMessagingTemplate.convertAndSend(D destination, Object payload)复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

生物序列分析

生物序列分析

Richard Durbin、Sean Eddy、Anders Krogh [等] / 王俊、郭一然、单杲 / 科学出版社 / 2010-8 / 60.00元

生物序列分析,ISBN:9787030284433,作者:(英)Durbin,R 等编著一起来看看 《生物序列分析》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换