IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 消息推送websocket -> 正文阅读

[网络协议]消息推送websocket

一、介绍

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
这个webSocket实现的前提是要进行一次浏览器向服务器发送一次请求,完成第一次握手,其实就是浏览器发起一次请求,与浏览器建立连接,建立连接之后双方意见达成一致,这种一致的意见就是将要共同使用websocket协议进行之后的通信。一旦这种协议建立完成,双方就能直接互相发送消息了。

二、优点

在没有用websocket时,想要及时获取服务端的更新数据,常用的两种方法:长链接、轮询;相比较这两种方式,websocket实在是有了太大的优势,既没有轮询那种耗费网络资源,也没有长链接那种耗费服务器资源。服务器是能够自主的进行给浏览器发送消息的,这是很关键的一点,有了自主性。

三、实现

springboot整合websocket

1.maven引入依赖

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

2.创建配置文件,开启websocket

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

// 开启WebSocket支持
@Configuration  
public class WebSocketConfig {  
    @Bean  
    public ServerEndpointExporter serverEndpointExporter() {  
        return new ServerEndpointExporter();  
    }  
  
} 

3.前端实现

原生js代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>websocket</title>
  <script src="/js/jquery-3.0.0.js"></script>
</head>
<body>
<h3>对谁发送消息:</h3>
<span>userId:</span><input type="text" id="userId"><br>
<span>消息:</span>
<input type="text" id="message">
<button id="bt">发送消息</button>
<br>
<span>使用websocket的发送信息的方法向服务器发送消息:</span>
<input type="text" id="websocketMessage">
<button id="websocketBtn">websocket发送消息</button>
<script>

  var webSocket = null;
  var bt = document.getElementById('bt');
  if ('WebSocket' in window) {
    //连接时带上userId
      webSocket = new WebSocket('ws://' + location.hostname + ':' + location.port + '/webSocket/2');
    // webSocket = new WebSocket('ws://localhost:8080/webSocket/2');
  } else {
    alert('浏览器不支持websocket');
  }
  webSocket.onopen = function (event) {
    console.log('建立连接');
  }
  webSocket.onclose = function (event) {
    console.log('连接关闭');
  }
  webSocket.onmessage = function (event) {
    alert('收到服务端发来的消息:' + event.data);
  }
  webSocket.onerror = function () {
    alert('websocket通信发生错误');
  }
  webSocket.onbeforeunload = function () {
    webSocket.close();
  }
  bt.onclick = function () {
    var userId = document.getElementById('userId').value;
    var message = document.getElementById('message').value;

    var userIdAndMessage = {'userId': userId, 'message': message};
    $.post("/sendMessage", userIdAndMessage)
  }
  $('#websocketBtn').click(function () {
    webSocket.send($('#websocketMessage').val());
  })
</script>
</body>
</html>

4.后端实现

(1)websocket连接

import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;

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.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
//用户连接的时候带上用户id
@ServerEndpoint("/webSocket/{userId}")
public class WebSocket {
  private Session session;
  private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();
  private static ConcurrentHashMap<Integer, Session> webSocketSession = new ConcurrentHashMap<Integer, Session>();
//用户连接,将userId和websocket.Session存入ConcurrentHashMap中,
  这样做为实现之后对指定人进行消息推送
  @OnOpen
  public void onOpen(Session session, @PathParam("userId") int userId) {
    this.session = session;
    webSocketSet.add(this);
    webSocketSession.put(userId, session);
    System.out.println("新连接者的用户号:" + userId);
    System.out.println("当前在线用户总数:" + webSocketSet.size());
  }
//连接关闭,关闭时要将ConcurrentHashMap中的断线用户信息清除掉
  @OnClose
  public void onClose() {
    webSocketSet.remove(this);
    int offLineUserId = 0;
    for (int userId : webSocketSession.keySet()) {
      if (webSocketSession.get(userId) == this) {
        offLineUserId = userId;
        webSocketSession.remove(userId);
        break;
      }
    }
    System.out.println("用户“" + offLineUserId + "”离线");
    System.out.println("在线人数:" + webSocketSession.size());
    System.out.println(webSocketSession);
  }
//接收客户端发来的websocket消息
  @OnMessage
  public void onMessage(String message) {
    System.out.println("收到客户端发来的消息:" + message);
  }

  public static void toUserSendMessage(int userId, String message) {
    try {
      webSocketSession.get(userId).getBasicRemote().sendText(message);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
//发出广播消息
  public void sendBroadcastMessage(String message) {
    for (WebSocket webSocket : webSocketSet) {
      System.out.println("广播消息,message:" + message);
      try {
        webSocket.session.getBasicRemote().sendText(message);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
}

(2)接收浏览器的请求,给指定人推送消息


import com.example.websocket.service.WebSocket;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.HttpServletResponse;

@Controller
public class SendMessageController {
  @PostMapping("/sendMessage")
  public void sendMessage(int userId, String message, HttpServletResponse response) {
    WebSocket.toUserSendMessage(userId, message);
  }
}

四、总结说明

这里后端使用了ConcurrentHashMap来存储websocket用户连接的信息,这样就是将信息存储到了内存中,对于内存的是有一定的耗费的。如果是对于将系统部署到多机上,那么需要调整或者换其他方法(像是将websocket用户连接信息暂存到数据库中等等)来进行对用户连接信息的储存。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-11 12:47:32  更:2021-08-11 12:48:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:31:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码