vue+webrtc(腾讯云) 实现直播功能 pc端+移动端

Websocket实现私聊和群聊

  • 1. websocket的概念
    • 1.1. 全双工概念
  • 2. websocket实现聊天室
    • 2.1. WebSocket API
      • 2.1.1. 构造方法
        • 2.1.1.1. 语法
        • 2.1.1.2. 参数
        • 2.1.1.3. 抛出异常
      • 2.1.2. 常量
      • 2.1.3. 属性
      • 2.1.4. 方法
      • 2.1.5. 事件
  • 3. websocket实现群聊或私聊或图片发送
    • 3.1. 项目的最终目录结构
    • 3.2. 依赖注入
    • 3.3. yml文件配置
    • 3.4. 注入ServerEndpointExporter
    • 3.5. Controller代码
    • 3.5. websocket实现群聊
      • 3.5.1. 服务器端代码
      • 3.5.2. 客户端代码
      • 3.5.3. 测试结果
    • 3.6. websocket实现私聊+群聊
      • 3.6.1. 服务器端代码
      • 3.6.2. 客户端代码
      • 3.6.3. SocketConfig代码
      • 3.6.4. 测试结果
    • 3.7. websocket实现聊天图片发送
      • 3.7.1. 服务端代码
      • 3.7.2. 客户端代码
      • 3.7.3. SocketConfig代码
      • 3.7.4. 测试结果

1. websocket的概念

websocket是一种在单个TCP连接上进行全双工通信的协议。websocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在websocket API中浏览器和服务器只需要完成一次握手,两者之间就可以直接创建持久性的连接,并进行双向数据传输。

1.1. 全双工概念

全双工是通讯传输的一个术语。通信允许数据在两个方面上同时传输,它在能力上相当于两个单工通信方式的结合。全双工指可以同时进行信号的双向传输(A—>B的同时B—>A)。单工指:只允许A向B传送信息,而B不能向A传送。

2. websocket实现聊天室

2.1. WebSocket API

WebSocket对象提供了用户创建和管理WebSocket连接,以及通过该连接发送和接收数据的API。

2.1.1. 构造方法
2.1.1.1. 语法

WebSocket(url [, protocols]);

2.1.1.2. 参数
  1. url:要连接的url,WebSocket服务器的url
  2. protocols:可选参数,一个协议字符串或者一个包含协议字符串的数组。这些字符串用于指定子协议,这样单个服务器可以实现多个WebSocket子协议。如果不指定协议字符串,则假定为空字符串。
2.1.1.3. 抛出异常

SECURITY_ERR:正在尝试连接的端口被阻止。

2.1.2. 常量
  1. WebSocket.CONNECTING == 0 连接中
  2. WebSocket.OPEN == 1 已连接
  3. WebSocket.CLOSING == 2 正在关闭
  4. WebSocket.CLOSED == 3 已关闭
2.1.3. 属性
  1. WebSocket.binaryType

    使用二进制的数据类型连接

  2. WebSocket.bufferedAmount(只读)

    未发送至服务器的字节数

  3. WebSocket.extensions(只读)

    服务器选择的扩展

  4. WebSocket.onopen

    用户指定连接成功后的回调函数

  5. WebSocket.onmessage

    用户指定从服务器接收到信息时的回调函数

  6. WebSocket.onerror

    用于指定连接失败后的回调函数

  7. WebSocket.onclose

    用于指定连接关闭后的回调函数

  8. WebSocket.url

    websocket的绝对路径

  9. WebSocket.readyState(只读)

    当前的连接状态

  10. WebSocket.protocol(只读)

    服务器选择的下属协议

2.1.4. 方法
  1. WebSocket.close([code, reason])

    关闭当前连接

  2. WebSocket.send(data)

    对要传输的数据进行排队

2.1.5. 事件

使用addEventListener()监听或将一个事件监听器赋值给本接口的oneventname属性,来监听下面的事件:

  1. open

    当一个WebSocket连接成功时触发,也可以通过onopen属性来设置

  2. message

    当一个WebSocket收发数据时触发,也可以通过onmessage属性来设置

  3. error

    当一个WebSocket连接因错误而关闭时触发,也可以通过onerror属性来设置

  4. close

    当一个WebSocket连接被关闭时触发,也可以通过onclose属性来设置

3. websocket实现群聊或私聊或图片发送

本文使用springboot+freemarker+websocket实现代码

3.1. 项目的最终目录结构

本图片分为三个小的项目:1.websocket实现群聊;2.websocket实现群聊和私聊;3.websocket实现聊天内容可以为图片

3.2. 依赖注入

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.AttackingApe.demo</groupId><artifactId>webSocket</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.6.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>net.sourceforge.nekohtml</groupId><artifactId>nekohtml</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.72</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins><resources><resource><directory>src/main/resources</directory></resource></resources></build>
</project>

3.3. yml文件配置

server:port: 20713tomcat:uri-encoding: UTF-8
spring:freemarker:suffix: .ftlcharset: UTF-8content-type: text/htmlhttp:encoding:charset: UTF-8force: trueenabled: true

3.4. 注入ServerEndpointExporter

package com.AttackingApe.demo.webSocket.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @author PengPan* @version 1.0* @date 2020/7/14 18:50*/
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}
}

3.5. Controller代码

package com.AttackingApe.demo.webSocket.Controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;import java.io.IOException;
import java.util.Map;/*** websocket应用* @author PengPan* @version 1.0* @date 2020/7/13 14:34*/
@RestController
@Slf4j
public class WebsocketController {@RequestMapping("/websocketTest")public ModelAndView sendMessage(Map<String, Object> map) throws IOException{try{log.info("跳转到websocket页面上");return new ModelAndView("webSocketClients", map);}catch (Exception e){log.info("页面跳转发生错误:{}", e.getMessage());map.put("msg", "请求错误");return new ModelAndView("error", map);}}
}

3.5. websocket实现群聊

实现内容:连接websocket的用户都可以进行聊天并显示所有人聊天以及对应的昵称。

3.5.1. 服务器端代码
package com.AttackingApe.demo.webSocket.util;import com.AttackingApe.demo.webSocket.Pojo.SocketConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;/*** @author PengPan* @version 1.0* @date 2020/7/15 18:23*/
@ServerEndpoint(value = "/websocket/{nickname}")
@Component
@Slf4j
public class MyWebsocket {private static Map<String, Session> map = new HashMap<>();private static CopyOnWriteArraySet<MyWebsocket> clients = new CopyOnWriteArraySet<>();private Session session;private String nickname;@OnOpenpublic void onOpen(Session session, @PathParam("nickname") String nickname){this.session = session;this.nickname = nickname;clients.add(this);log.info("有新用户加入,当前人数为:", clients.size());this.session.getAsyncRemote().sendText(nickname + "已加入连接,当前人数为:" + clients.size());}@OnClosepublic void onClose(){clients.remove(this);log.info("有用户断开连接,当前人数为:{}", clients.size());}@OnMessagepublic void onMessage(String message, Session session, @PathParam("nickname") String nickname){log.info("来自客户端:{}发来的消息:{}", nickname, message);broadcast(nickname + ":" + message);}@OnErrorpublic void onError(Session session, Throwable error){log.error("出现错误");error.printStackTrace();}/*** 自定义群发消息* @param message*/public void broadcast(String message){for (MyWebsocket websocket : clients){//异步发送消息websocket.session.getAsyncRemote().sendText(message);}}
}
3.5.2. 客户端代码
<!DOCTYPE HTML>
<html>
<head><meta charset="UTF-8"><title>My WebSocket</title><style>#message{margin-top:40px;border:1px solid gray;padding:20px;}</style>
</head>
<body>
昵称:<input type="text" id="nickname"/>
<button οnclick="conectWebSocket()">连接WebSocket</button>
<button οnclick="closeWebSocket()">断开连接</button>
<hr />
<br />
消  息:<input id="text" type="text" /><button οnclick="send()">发送消息</button>
<div id="message"></div>
</body>
<script type="text/javascript">var websocket = null;function conectWebSocket(){var nickname = document.getElementById("nickname").value;if(nickname == "" || nickname == null){alert("请输入昵称");return;}//判断当前浏览器是否支持WebSocketif ('WebSocket'in window) {websocket = new WebSocket("ws://10.4.4.83:20713/websocket/" + nickname);} else {alert('Not support websocket')}//连接发生错误的回调方法websocket.onerror = function() {setMessageInnerHTML("error");};//连接成功建立的回调方法websocket.onopen = function(event) {setMessageInnerHTML("Loc MSG: 成功建立连接");}//接收到消息的回调方法websocket.onmessage = function(event) {setMessageInnerHTML(event.data);}//连接关闭的回调方法websocket.onclose = function() {setMessageInnerHTML("Loc MSG:关闭连接");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function() {websocket.close();}}//将消息显示在网页上function setMessageInnerHTML(innerHTML) {document.getElementById('message').innerHTML += innerHTML + '<br/>';}//关闭连接function closeWebSocket() {websocket.close();}//发送消息function send() {var message = document.getElementById('text').value;websocket.send(message);}
</script>
</html>
3.5.3. 测试结果

在这里插入图片描述在这里插入图片描述

3.6. websocket实现私聊+群聊

实现内容:A可以在公屏上输入内容,大家都可以看见。也可以选择输入频道,只和每一个人聊天。

3.6.1. 服务器端代码
package com.AttackingApe.demo.webSocket.util;import com.AttackingApe.demo.webSocket.Pojo.SocketConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;/*** @author PengPan* @version 1.0* @date 2020/7/15 18:23*/
@ServerEndpoint(value = "/websocket/{nickname}")
@Component
@Slf4j
public class MyWebsocket {private static Map<String, Session> map = new HashMap<>();private static CopyOnWriteArraySet<MyWebsocket> clients = new CopyOnWriteArraySet<>();private Session session;private String nickname;@OnOpenpublic void onOpen(Session session, @PathParam("nickname") String nickname){this.session = session;this.nickname = nickname;map.put(session.getId(), session);clients.add(this);log.info("有新用户加入,当前人数为:", clients.size());this.session.getAsyncRemote().sendText(nickname + "已成功连接(其频道号为:" + session.getId() + "),当前在线人数为:" + clients.size());}@OnClosepublic void onClose(){clients.remove(this);log.info("有用户断开连接,当前人数为:{}", clients.size());}@OnMessagepublic void onMessage(String message, Session session, @PathParam("nickname") String nickname){log.info("来自客户端:{}发来的消息:{}", nickname, message);SocketConfig socketConfig;ObjectMapper objectMapper = new ObjectMapper();try{socketConfig = objectMapper.readValue(message, SocketConfig.class);if(socketConfig.getType() == 1){  //私聊socketConfig.setFromUser(session.getId());Session fromSession = map.get(socketConfig.getFromUser());Session toSession = map.get(socketConfig.getToUser());if(toSession != null){  //接受者存在,发送以下消息给接受者和发送者fromSession.getAsyncRemote().sendText(nickname + ":" + socketConfig.getMsg());toSession.getAsyncRemote().sendText(nickname + ":" + socketConfig.getMsg());}else{  //发送者不存在,发送以下消息给发送者fromSession.getAsyncRemote().sendText("频道号不存在或对方不在线");}}else{  //群聊broadcast(nickname + ":" + socketConfig.getMsg());}}catch (Exception e){log.error("发送消息出错");e.printStackTrace();}}@OnErrorpublic void onError(Session session, Throwable error){log.error("出现错误");error.printStackTrace();}/*** 自定义群发消息* @param message*/public void broadcast(String message){for (MyWebsocket websocket : clients){//异步发送消息websocket.session.getAsyncRemote().sendText(message);}}
}
3.6.2. 客户端代码
<!DOCTYPE HTML>
<html>
<head><meta charset="UTF-8"><title>My WebSocket</title><style>#message{margin-top:40px;border:1px solid gray;padding:20px;}</style>
</head>
<body>
昵称:<input type="text" id="nickname"/>
<button οnclick="conectWebSocket()">连接WebSocket</button>
<button οnclick="closeWebSocket()">断开连接</button>
<hr />
<br />
消  息:<input id="text" type="text" />
频道号:<input id="toUser" type="text"/>
<button οnclick="send()">发送消息</button>
<div id="message"></div>
</body>
<script type="text/javascript">var websocket = null;function conectWebSocket(){var nickname = document.getElementById("nickname").value;if(nickname == "" || nickname == null){alert("请输入昵称");return;}//判断当前浏览器是否支持WebSocketif ('WebSocket'in window) {websocket = new WebSocket("ws://10.4.4.83:20713/websocket/" + nickname);} else {alert('Not support websocket')}//连接发生错误的回调方法websocket.onerror = function() {setMessageInnerHTML("error");};//连接成功建立的回调方法websocket.onopen = function(event) {setMessageInnerHTML("Loc MSG: 成功建立连接");}//接收到消息的回调方法websocket.onmessage = function(event) {setMessageInnerHTML(event.data);}//连接关闭的回调方法websocket.onclose = function() {setMessageInnerHTML("Loc MSG:关闭连接");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function() {websocket.close();}}//将消息显示在网页上function setMessageInnerHTML(innerHTML) {document.getElementById('message').innerHTML += innerHTML + '<br/>';}//关闭连接function closeWebSocket() {websocket.close();}//发送消息function send() {var message = document.getElementById('text').value;var toUser = document.getElementById('toUser').value;var socketConfig = {msg:message,toUser:toUser};if(toUser == "" || toUser == null){socketConfig.type = 0;}else{socketConfig.type = 1;}websocket.send(JSON.stringify(socketConfig));}
</script>
</html>
3.6.3. SocketConfig代码
package com.AttackingApe.demo.webSocket.Pojo;import lombok.Data;/*** @author PengPan* @version 1.0* @date 2020/7/16 15:41*/
@Data
public class SocketConfig {//聊天类型 0:群聊  1:私聊private int type;//发送者private String fromUser;//接受者private String toUser;//消息private String msg;//消息类型 1:文本  2:图片private int code;
}
3.6.4. 测试结果

在这里插入图片描述在这里插入图片描述在这里插入图片描述

3.7. websocket实现聊天图片发送

实现内容:聊天的时候可以传入图片。

3.7.1. 服务端代码
package com.AttackingApe.demo.webSocket.util;import com.AttackingApe.demo.webSocket.Pojo.SocketConfig;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;/*** @author PengPan* @version 1.0* @date 2020/7/15 18:23*/
@ServerEndpoint(value = "/websocket/{nickname}")
@Component
@Slf4j
public class MyWebsocket {private static Map<String, Session> map = new HashMap<>();private static CopyOnWriteArraySet<MyWebsocket> clients = new CopyOnWriteArraySet<>();private Session session;private String nickname;@OnOpenpublic void onOpen(Session session, @PathParam("nickname") String nickname){this.session = session;this.nickname = nickname;map.put(session.getId(), session);clients.add(this);log.info("有新用户加入,当前人数为:", clients.size());JSONObject jsonObject = new JSONObject();jsonObject.put("msg",nickname + "已成功连接(其频道号为:" + session.getId() + "),当前在线人数为:" + clients.size());jsonObject.put("code", 1);this.session.getAsyncRemote().sendText(jsonObject.toJSONString());}@OnClosepublic void onClose(){clients.remove(this);log.info("有用户断开连接,当前人数为:{}", clients.size());}@OnMessagepublic void onMessage(String message, Session session, @PathParam("nickname") String nickname){log.info("来自客户端:{}发来的消息:{}", nickname, message);SocketConfig socketConfig;ObjectMapper objectMapper = new ObjectMapper();JSONObject jsonObject = new JSONObject();jsonObject.put("code", JSONObject.parseObject(message).get("code"));try{socketConfig = objectMapper.readValue(message, SocketConfig.class);jsonObject.put("nickname", nickname + ":");if(socketConfig.getType() == 1){  //私聊socketConfig.setFromUser(session.getId());Session fromSession = map.get(socketConfig.getFromUser());Session toSession = map.get(socketConfig.getToUser());if(toSession != null){  //接受者存在,发送以下消息给接受者和发送者jsonObject.put("msg", socketConfig.getMsg());fromSession.getAsyncRemote().sendText(jsonObject.toJSONString());toSession.getAsyncRemote().sendText(jsonObject.toJSONString());}else{  //发送者不存在,发送以下消息给发送者jsonObject.put("msg", "频道号不存在或对方不在线");fromSession.getAsyncRemote().sendText("频道号不存在或对方不在线");}}else{  //群聊jsonObject.put("msg", socketConfig.getMsg());broadcast(jsonObject.toJSONString());}}catch (Exception e){log.error("发送消息出错");e.printStackTrace();}}@OnErrorpublic void onError(Session session, Throwable error){log.error("出现错误");error.printStackTrace();}/*** 自定义群发消息* @param message*/public void broadcast(String message){for (MyWebsocket websocket : clients){//异步发送消息websocket.session.getAsyncRemote().sendText(message);}}
}
3.7.2. 客户端代码
<!DOCTYPE HTML>
<html>
<head><meta charset="UTF-8"><title>My WebSocket</title><style>#message{margin-top:40px;border:1px solid gray;padding:20px;}</style>
</head>
<body>
昵称:<input type="text" id="nickname"/>
<button οnclick="conectWebSocket()">连接WebSocket</button>
<button οnclick="closeWebSocket()">断开连接</button>
<hr />
<br />
消  息:<input id="text" type="text" />
频道号:<input id="toUser" type="text"/>
<button οnclick="send()">发送消息</button>
<input type="file" id="file" οnchange="chooseFile()"/>
<div id="message"></div>
</body>
<script type="text/javascript">var websocket = null;function conectWebSocket(){var nickname = document.getElementById("nickname").value;if(nickname == "" || nickname == null){alert("请输入昵称");return;}//判断当前浏览器是否支持WebSocketif ('WebSocket'in window) {websocket = new WebSocket("ws://10.4.4.83:20713/websocket/" + nickname);} else {alert('Not support websocket')}//连接发生错误的回调方法websocket.onerror = function() {setMessageInnerHTML("error");};//连接成功建立的回调方法websocket.onopen = function(event) {setMessageInnerHTML("Loc MSG: 成功建立连接");}//接收到消息的回调方法websocket.onmessage = function(event) {var json = JSON.parse(event.data);if(json.code == 1){setMessageInnerHTML(json.nickname + json.msg);}else if(json.code == 2){setMessageInnerHTML(json.nickname);setIconInnerHTML(json.msg);}}//连接关闭的回调方法websocket.onclose = function() {setMessageInnerHTML("Loc MSG:关闭连接");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function() {websocket.close();}}//将文本消息显示在网页上function setMessageInnerHTML(innerHTML) {document.getElementById('message').innerHTML += innerHTML + '<br/>';}//将图片消息显示在网页上function setIconInnerHTML(innerHTML) {document.getElementById('message').innerHTML = document.getElementById('message').innerHTML + '<img width="150px" src='+innerHTML+'>' + '<br/>';}//关闭连接function closeWebSocket() {websocket.close();}//发送文本消息function send() {var message = document.getElementById('text').value;var toUser = document.getElementById('toUser').value;var socketConfig = {code:1,msg:message,toUser:toUser};if(toUser == "" || toUser == null){socketConfig.type = 0;}else{socketConfig.type = 1;}websocket.send(JSON.stringify(socketConfig));}//发送图片消息function chooseFile() {var fileList = document.getElementById("file").files;var type = fileList[0].type;var toUser = document.getElementById('toUser').value;if(fileList.length > 0){var fileReader = new FileReader();fileReader.readAsDataURL(fileList[0]);fileReader.onload = function (e) {var socketConfig = {msg: e.target.result,toUser: toUser,code: 2};if (toUser == "" || toUser == null) {socketConfig.type = 0;} else {socketConfig.type = 1;}websocket.send(JSON.stringify(socketConfig));}}}
</script>
</html>
3.7.3. SocketConfig代码
package com.AttackingApe.demo.webSocket.Pojo;import lombok.Data;/*** @author PengPan* @version 1.0* @date 2020/7/16 15:41*/
@Data
public class SocketConfig {//聊天类型 0:群聊  1:私聊private int type;//发送者private String fromUser;//接受者private String toUser;//消息private String msg;//消息类型 1:文本  2:图片private int code;
}
3.7.4. 测试结果

在这里插入图片描述在这里插入图片描述在这里插入图片描述

# websocket# javascript

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/856060.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CI /CD学习

CI/CD概述 CI/CD 是持续集成和持续交付/部署的缩写&#xff0c;旨在简化并加快软件开发生命周期。 持续集成&#xff08;CI&#xff09;是指自动且频繁地将代码更改集成到共享源代码存储库中的做法。持续交付和/或持续部署&#xff08;CD&#xff09;是一个由两部分组成的过程…

02. Java操作系统的并发

1. 前言 本节内容是从操作系统的层面谈并发&#xff0c;本节课程我们需要掌握如下内容&#xff1a; 掌握并发编程的定义&#xff0c;并发编程的定义是了解并发的前提基础&#xff1b;从 CPU 谈并发诞生的意义&#xff0c;一切语言的基础都是操作系统&#xff0c;CPU 的并发与…

排序算法及源代码

堆排序&#xff1a; 在学习堆之后我们知道了大堆和小堆&#xff0c;对于大堆而言第一个节点就是对大值&#xff0c;对于小堆而言&#xff0c;第一个值就是最小的值。如果我们把第一个值与最后一个值交换再对最后一个值前面的数据重新建堆&#xff0c;如此下去就可以实现建堆排…

#01算法的复杂性

时间复杂度 public void print(int n){int a 1; //执行1次for(int i0;i<n;i){//执行n次System.out.println(ai);//执行n次} } 该算法的时间复杂度是O(2n1) 大O会忽略常数、低阶和系数&#xff0c;最终记作O(n); 如果算法的执行时间和数据规模n无关&#xff0c;则是常量阶…

Apple - Authorization Services Programming Guide

本文翻译整理自&#xff1a;Authorization Services Programming Guide&#xff08;更新日期&#xff1a;2011-10-19 https://developer.apple.com/library/archive/documentation/Security/Conceptual/authorization_concepts/01introduction/introduction.html#//apple_ref/d…

JavaScript基础部分知识点总结(Part3)

函数的概念 1. 函数的概念 在JS 里面&#xff0c;可能会定义非常多的相同代码或者功能相似的代码&#xff0c;这些代码可能需要大量重复使用。虽然for循环语句也能实现一些简单的重复操作&#xff0c;但是比较具有局限性&#xff0c;此时我们就可以使用JS 中的函数。函数&…

Tensorflow入门实战 T05-运动鞋识别

目录 一、完整代码 二、训练过程 &#xff08;1&#xff09;打印2行10列的数据。 &#xff08;2&#xff09;查看数据集中的一张图片 &#xff08;3&#xff09;训练过程&#xff08;训练50个epoch&#xff09; &#xff08;4&#xff09;训练结果的精确度 三、遇到的问…

安装VSCode创建注册表出错,RegCreateKey错误码5

今天对VSCode进行做更新安装&#xff0c;谁知道安装到最后弹出下面这么个错误 找到windows下管用的一种解决办法&#xff1a; winR打开运行&#xff0c;输入 regedit找到错误提示中的路径&#xff0c;HKEY_CURRENT_USER\Software\Classes\VSCode.class\open (图中的错误注册表…

第 三 方 组 件 e l e m e n t - u i[Vue]

一、组件之间的传值 组件可以由内部的Data提供数据&#xff0c;也可以由父组件通过prop的方式传值。 兄弟组件之间可以通过Vuex等统一数据源提供数据共享 第一种 Movie.vue <template><div><h1>我才不要和你做朋友</h1></div></template&…

嵌入式开发十九:SysTick—系统定时器

在前面实验中我们使用到的延时都是通过SysTick进行延时的。 我们知道&#xff0c;延时有两种方式&#xff1a;软件延时&#xff0c;即CPU 循环等待产生的&#xff0c;这个延时是不精确的。第二种就是滴答定时器延时&#xff0c;本篇博客就来介绍 STM32F4 内部 SysTick 系统定时…

高德地图轨迹回放/轨迹播放

前言 本篇文章主要介绍高德地图的轨迹回放或播放的实现过程&#xff0c;是基于vue2实现的功能&#xff0c;同时做一些改动也是能够适配vue3的。其中播放条是用的是element UI中的el-slider组件&#xff0c;包括使用到的图标也是element UI自带的。可以实现轨迹的播放、暂停、停…

【windows|004】BIOS 介绍及不同品牌电脑和服务器进入BIOS设置的方法

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…

【ARM】如何通过Keil MDK查看芯片的硬件信息

【更多软件使用问题请点击亿道电子官方网站】 1、文档目标&#xff1a; 解决在开发过程中对于开发项目所使用的的芯片的参数查看的问题 2、问题场景&#xff1a; 在项目开发过程中&#xff0c;经常需要对于芯片的时钟、寄存器或者一些硬件参数需要进行确认。大多数情况下是需…

wps-文档-js宏-批量修改表格格式

目录 前言开启JS宏我的脚本参考API文档 前言 由于需要修改word的表格的格式&#xff0c;一个一个的修改太慢了&#xff0c;所以需要通过宏的方式来修改&#xff0c;需要注意的是低版本可能没有JS宏… 开启JS宏 切换到工具–>点击开发工具 点击之后功能栏会变化成这样 选…

Dell戴尔灵越Inspiron 16 Plus 7640/7630笔记本电脑原装Windows11下载,恢复出厂开箱状态预装OEM系统

灵越16P-7630系统包: 链接&#xff1a;https://pan.baidu.com/s/1Rve5_PF1VO8kAKnAQwP22g?pwdjyqq 提取码&#xff1a;jyqq 灵越16P-7640系统包: 链接&#xff1a;https://pan.baidu.com/s/1B8LeIEKM8IF1xbpMVjy3qg?pwdy9qj 提取码&#xff1a;y9qj 戴尔原装WIN11系…

CFD笔记

CFD 定常流动与非定常流动 定常流动&#xff1a;流体流动过程中各物理量均与时间无关; 非定常流动&#xff1a;流体流动过程中某个或某些物理量与时间有关. 运动黏度 运动粘度定义&#xff1a; v μ ρ v \frac{\mu}{\rho} vρμ​&#xff0c;其中 μ \mu μ​表示粘度…

Node.js进阶——数据库

文章目录 一、步骤1、安装操作 MySQL数据库的第三方模块(mysql)2、通过 mysql 模块连接到 MySQL 数据库3、测试 二、操作 mysql 数据库1、查询语句2、插入语句3、插入语句快捷方式4、更新数据5、更新语句快捷方式6、删除数据7、标记删除 二、前后端的身份认证1、web开发模式1&a…

如何用python调用C++处理图片

一. 背景 用pyhton可直接调用C&#xff0c;减少重写的工作量&#xff1b;部分逻辑运算&#xff0c;C的执行效率高&#xff0c;可进行加速。 下面就一个简单的C滤镜&#xff08;彩色图转灰度图&#xff09;为例&#xff0c;展示python调用C 二. 代码实现 代码结构如下&#x…

如何解决跨区域文件传输存在的安全管控问题?

⼤型企业和集团为扩⼤市场份额、优化资源配置&#xff0c;会在不同地区设⽴多级下属分⽀机构、研发中心、实验室等&#xff0c;存在研发数据横向或纵向流转的需求&#xff0c;研发数据进行跨区域文件传输的场景。跨区域可能是网络区域&#xff0c;也可能是地理区域&#xff0c;…

2-10 基于matlab的动态时间归整(DTW)算法

基于matlab的动态时间归整&#xff08;DTW&#xff09;算法。16页的试验文档。以一个能识别数字0&#xff5e;9的语音识别系统的实现过程为例&#xff0c;阐述了基于DTW算法的特定人孤立词语音识别的基本原理和关键技术。其中包括对语音端点检测方法、特征参数计算方法和DTW算法…