【项目实践day10】WebSocket介绍及入门实践

WebSocket介绍

  • 基于 TCP 的一种新的网络协议
  • 实现了浏览器与服务器全双工通信
    • 浏览器和服务器只需要完成一次握手
    • 两者之间就可以创建持久性的连接, 并进行双向数据传输
      • 浏览器可以向服务器传输数据,服务器可以主动向浏览器传输数据,他们之间是双向的。

WebSocket与Http对比

Http

  1. http交互的顺序:客户端发送请求,服务器给他响应(顺序不能颠倒)。服务器不会主动给浏览器发送消息,一定是浏览器先请求服务器,服务器才给响应。------通常称为请求响应模式

  2. http建立连接:客户端发送完之后,会建立连接,响应完请求之后,连接就会不存在,所以这种连接叫做短连接

WebSocket

  1. 客户端发送请求给服务器,握手;服务器给客户端一个应答;一旦应答之后,就建立好连接了,就可以双向通信了
  2. 客户端可以主动向服务器发送数据,服务器也可以主动向客户端发送数据

WebSocket应用场景

  • 视频弹幕:页面没有刷新,弹幕随时都可以出现在浏览器界面上。实际上是通过websorket主动将信息推送上来
  • 网页聊天:网站上跟客服进行聊天,发送就发过去了,然后对面说的话也能及时出现在界面上。通过服务器主动把消息推送到网页上
  • 体育实况更新:页面没有刷新,但是页面实时更新
  • 股票基金报价实时更新:通过websorket主动将数据推送到页面上进行展示,不需要页面发请求获取数据,而是服务器主动推上来的数据

案例实现

导入websocket.html

直接使用websocket.html页面作为WebSocket客户端

html 复制代码
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>WebSocket Demo</title>
</head>
<body>
    <input id="text" type="text" />
    <button onclick="send()">发送消息</button>
    <button onclick="closeWebSocket()">关闭连接</button>
    <div id="message">
    </div>
</body>
<script type="text/javascript">
    var websocket = null;
    var clientId = Math.random().toString(36).substr(2);

    //判断当前浏览器是否支持WebSocket
    if('WebSocket' in window){
        //连接WebSocket节点
        websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);
    }
    else{
        alert('Not support websocket')
    }

    //连接发生错误的回调方法
    websocket.onerror = function(){
        setMessageInnerHTML("error");
    };

    //连接成功建立的回调方法
    websocket.onopen = function(){
        setMessageInnerHTML("连接成功");
    }

    //接收到消息的回调方法
    websocket.onmessage = function(event){
        setMessageInnerHTML(event.data);
    }

    //连接关闭的回调方法
    websocket.onclose = function(){
        setMessageInnerHTML("close");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function(){
        websocket.close();
    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML){
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //发送消息
    function send(){
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
	
	//关闭连接
    function closeWebSocket() {
        websocket.close();
    }
</script>
</html>

注意:

html 复制代码
websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);
  1. 客户端发送一个握手的请求,端口是8080,后面是一个路径,类似于Controller,按照路径去匹配。注意:协议不同,这里是ws协议也就是websocket协议,之前的都是http协议
  2. 握手之后,服务器和客户端就建立了长连接,就可以进行双向通信了

导入WebSocket的maven坐标

xml 复制代码
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

导入WebSocket服务端组件

导入WebSocket服务端组件WebSocketServer,用于和客户端通信

  1. 服务器应当有一个组件,与客户端通信
  2. 作用:用于与客户端通信,类似于SpringMVC的Controller
  3. Controller响应客户端发送的http请求
  4. 这个WebSocketServer也是与客户端进行通信的,只是这次客户端是基于webSocket方式发送的
java 复制代码
package com.sky.websocket;

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.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * WebSocket服务
 */
@Component // 最终交给Spring容器去管理
// 根据路径进行匹配,这样就能请求到当前服务器组件,与Controller很像,都是根据路径去匹配
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {

    //存放会话对象
    private static Map<String, Session> sessionMap = new HashMap();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen  // 回调方法
    // @PathParam路径参数
    public void onOpen(Session session, @PathParam("sid") String sid) {
        System.out.println("客户端:" + sid + "建立连接");
        sessionMap.put(sid, session);
    }

    /**
     * 收到客户端消息后调用的方法
     * 类似与Controller
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, @PathParam("sid") String sid) {
        System.out.println("收到来自客户端:" + sid + "的信息:" + message);
    }

    /**
     * 连接关闭调用的方法
     *
     * @param sid
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        System.out.println("连接断开:" + sid);
        sessionMap.remove(sid);
    }

    /**
     * 群发
     * 没有加注解,需要主动去掉这个方法
     * @param message
     */
    public void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                //服务器向客户端发送消息!!!!!!!
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

导入配置类WebSocketConfiguration

导入配置类WebSocketConfiguration,注册WebSocket的服务端组件

  1. 做一个配置,让websocket生效
java 复制代码
package com.sky.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * WebSocket配置类,用于注册WebSocket的Bean
 */
@Configuration
public class WebSocketConfiguration {

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

}

导入定时任务类WebSocketTask

导入定时任务类WebSocketTask,定时向客户端推送数据

  1. 如何进行测试?提供定时任务类,定时推送数据
java 复制代码
package com.sky.task;

import com.sky.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Component
public class WebSocketTask {
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 通过WebSocket每隔5秒向客户端发送消息
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void sendMessageToClient() {
        webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
    }
}

测试

  1. 启动项目
  2. 双击html界面
    1. 只要打开界面,就相当于建立了连接
    2. 就会收到类似于如下的消息
      1. 因为这是定时类中的,定时发送的
  3. 在html界面的文本框中输入消息,点击发送消息
    1. 该步骤是为了验证双向通信
    2. 刚刚展示的是服务器主动给客户端发送请求
    3. 这里是客户端主动给服务器发送请求
    4. 此时,服务器端会收到消息
  4. 关闭连接
    1. 即为关闭连接,如果想重新开启连接,直接刷新界面即可

参考网站

参考网站

相关推荐
小突突突1 小时前
个人博客系统测试报告
运维·网络·功能测试
O。o.尊都假都1 小时前
socket套接字的超时控制
单片机·嵌入式硬件·网络协议
triticale1 小时前
【Java】网络编程(Socket)
java·网络·socket
wanhengidc2 小时前
服务器中存储空间不足该怎么办?
运维·服务器·网络
soulermax2 小时前
数字ic后端设计从入门到精通4(含fusion compiler, tcl教学)CMOS VLSI Design
网络·硬件架构
bing_1583 小时前
什么是IoT长连接服务?
网络·物联网·长连接服务
christine-rr3 小时前
【25软考网工】第六章(4)VPN虚拟专用网 L2TP、PPTP、PPP认证方式;IPSec、GRE
运维·网络·网络协议·网络工程师·ip·软考·考试
小白自救计划3 小时前
网络协议分析 实验四 ICMPv4与ICMPv6
网络·网络协议
purrrew4 小时前
【Java ee初阶】网络编程 UDP socket
java·网络·网络协议·udp·java-ee
python算法(魔法师版)4 小时前
API安全
网络·物联网·网络协议·安全·网络安全