一、什么是webscoket
WebSockets 是一种先进的技术,它可以在用户的浏览器和服务器之间打开交互式通信会话。使用此 API,可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应。
WebSockets 这种技术中有一个接口名为WebSocket,它是一个用于连接 WebSocket 服务器的主要接口,之后可以在这个连接上发送和接受数据。接下来的案例则是使用该接口创建一个WebSocket对象来进行管理。
二、WebSocket的优势与局限性
WebSocket的优势:
-
双向实时通信:WebSocket提供了双向的实时信能力,客户端和服务器可以通过该协议进行双向数据传输,实时反馈更新信息,实现即时通讯、实时数据推送等功能。
-
较低的延迟:与传统的HTTP请求相比,WebSocket降低了通信的开销,减少了传输和处理数据的延迟,因此可以更快进行实时数据传输。
-
更高的性能:由于WebSocket使用较少的头部信息和更有效的消息传输格式,因此在相同带宽下可以传输更多的数据,提高了性能和效率。
-
广泛的浏览器支持:WebSocket是HTML5的一部分,并且得到了大多数现代浏览器的支持,因此它可以在各种平台和设备上使用。
-
连接保持:与传统的HTTP请求不同,WebSocket连接保持在建立之后,双方可以随时进行数据传输,避免了不必要的连接和断开操作。
WebSocket的局限性:
-
兼容性问题:虽然现代浏览器广泛支持WebSocket,但在某些旧版本或特定设备上可能存在兼容性问题。为了兼容性,可以使用轮训技术(如长轮询)作为备选方案。
-
部署和维护复杂性:WebSocket服务器的设置和配置可能比传统的Web服务器复杂一些,需要专门的服务器环境和配置。
-
安全性问题:由于WebSocket是在HTTP协议的基础上建立的,它们共享相同的安全风险,例如跨站点脚本(XSS)和跨站请求伪造(CSRF)。因此,在使用WebSocket时需要考虑到安全性,并采取适当的安全措施。
-
扩展问题:WebSocket协议还不支持像HTTP/2那样的一些高级特性,例如头部压缩和流量控制。在某些特殊情况下,可能需要通过其他方式实现这些功能。
三、创建对象
使用WebSocket接口创建对象,在创建对象之前,判断当前使用的浏览器是否支持该技术,不支持则无法进行一下步操作。使用WebSocket接口中的构造器创建对象,构造器中传入要连接的 URL,也就是WebSocket 服务器将响应的 URL。其中ws表示使用的是WebSocket协议;还有一种wss相较于ws更为安全,他们类似于http和https。****
if(typeof(WebSocket) === "undefined"){
alert("您的浏览器不支持WebSocket")
}
四、处理事件
在上面对象创建成功的基础上,就可以使用该对象的处理事件了,主要分为以下四种
事件 | 事件监听器 | 描述 |
---|---|---|
open | webSocket.onopen | 用于指定链接成功后的回调函数 |
message | webSocket.onmessage | 用于指定当从服务器接受到信息时的回调函数 |
error | webSocket.onerror | 用于指定连接失败后的回调函数 |
close | webSocket.onclose | 用于指定链接关闭后的回调函数 |
五、前端代码演示(H5)
此处代码可以直接拿来使用,但是需要修改链接地址
<template>
<div @click="send()">
发送信息
</div>
</template>
export default {
data () {
return {
path:"ws://ip:端口/服务名/参数/", //这是链接的IP地址
socket:""
}
},
mounted () {
// 初始化
this.init()
},
methods: {
init () {
if(typeof(WebSocket) === "undefined"){
alert("您的浏览器不支持socket")
}else{
// 实例化socket
this.socket = new WebSocket(this.path)
// 监听socket连接
this.socket.onopen = this.open
// 监听socket错误信息
this.socket.onerror = this.error
// 监听socket消息
this.socket.onmessage = this.getMessage
}
},
//链接正确的信息
open () {
console.log("socket连接成功")
},
//链接错误的信息
error () {
console.log("连接错误")
},
//监听后端返回的信息,触发页面更新
getMessage (msg) {
console.log(msg.data)
},
// 发送消息给被连接的服务端
send () {
// 将要传递的参数编码为字符串,这里使用JSON格式
const params = {
param1: param1,
param2: param2,
};
const message = JSON.stringify(params);
this.socket.send(message)
},
//关闭时触发的事件
close: function () {
console.log("socket已经关闭")
}
},
// 移除监听事件
destroyed () {
// 销毁监听
this.socket.onclose = this.close
}
}
六、前端代码演示(uni-app)
此处代码可以直接拿来使用,但是需要修改链接地址
<template>
<view class="page">
<view class="demo" >
<view style="font-size: 20px">
测试websocket
</view>
<view style="margin-top: 20px">
<view class="" style="display: flex">
<view @click="connectSocketInit()" style="color: #2b69ff;cursor: pointer">
链接websocket
</view>
<view @click="closeSocket()" style="color: red;cursor: pointer;margin-left: 30px">
关闭websocket
</view>
</view>
<view style="display: flex ;margin-top: 20px">
<input v-model="sendInput" class="flex1" type="text"
placeholder-style="color:#999999" style="background: #e8e8e8;"/>
<view @click="clickRequest()" style="color: #2b69ff;cursor: pointer">
发送信息
</view>
</view>
</view>
<view v-for="(item,index) in OkMsg" :key="index" style="margin-top: 20px">
{{item.time}}
{{item.content}}
</view>
</view>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {
webSocketTask:null,
// path:"ws://ip:端口/服务名/参数/", //这是链接的IP地址
// path:"ws://124.222.224.186:8800", //这是链接的IP地址
path:"ws://192.168.35.95:8080/ws", //这是链接的IP地址,此处地址是在网上找的,
socket:"",
OkMsg:[],//当前信息
sendInput:'',//发送的消息
socketTask: null,
// 确保websocket是打开状态
is_open_socket: false
};
},
onLoad(){
//进入页面打开socket
this.connectSocketInit()
},
onShow(){
// 接收websocket消息及处理
},
onUnload() {
uni.closeSocket({
success: () => {
console.info("退出成功")
},
})
},
methods:{
// 进入这个页面的时候创建websocket连接【整个页面随时使用】
connectSocketInit() {
// 创建一个this.socketTask对象【发送、接收、关闭socket都由这个对象操作】
this.socketTask = uni.connectSocket({
// 【非常重要】必须确保你的服务器是成功的,如果是手机测试千万别使用ws://127.0.0.1:9099【特别容易犯的错误】
url: this.path,
success(data) {
console.log("websocket连接成功");
},
});
// 消息的发送和接收必须在正常连接打开中,才能发送或接收【否则会失败】
this.socketTask.onOpen((res) => {
console.log("WebSocket连接正常打开中...!");
this.is_open_socket = true;
// 注:只有连接正常打开中 ,才能正常成功发送消息
this.socketTask.send({
data: "uni-app发送一条消息",
async success() {
console.log("消息发送成功");
},
});
// 注:只有连接正常打开中 ,才能正常收到消息
this.socketTask.onMessage((res) => {
console.log("收到服务器内容:" + res.data);
let now = new Date();
let currentTime = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
if (!res.data.includes('开发或编程上遇到什么问题,可以在这输入向我提问')){
this.OkMsg.push(
{
content:res.data,
time:currentTime
}
)
}
});
})
// 这里仅是事件监听【如果socket关闭了会执行】
this.socketTask.onClose(() => {
console.log("已经被关闭了")
let now = new Date();
let currentTime = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
this.OkMsg.push(
{
content:'已经被关闭了',
time:currentTime
}
)
})
},
// 关闭websocket【离开这个页面的时候执行关闭】
closeSocket() {
this.socketTask.close({
success(res) {
this.is_open_socket = false;
console.log("关闭成功", res)
},
fail(err) {
console.log("关闭失败", err)
}
})
},
clickRequest() {
if (this.is_open_socket) {
// websocket的服务器的原理是:发送一次消息,同时返回一组数据【否则服务器会进去死循环崩溃】
this.socketTask.send({
data: this.sendInput,
async success() {
console.log("消息发送成功");
},
});
}
},
},
}
</script>
<style lang="scss" scoped>
</style>
七、后端代码演示
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
//依赖:
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
</dependency>
@ServerEndpoint("/echo")
public class EchoServer {
@OnOpen
public void onOpen(Session session) {
System.out.println("WebSocket 连接已经建立。");
}
@OnMessage
public void onMessage(String message, Session session) throws IOException {
System.out.println("收到客户端消息:" + message);
session.getBasicRemote().sendText("服务器收到消息:" + message);
}
@OnClose
public void onClose() {
System.out.println("WebSocket 连接已经关闭。");
}
@OnError
public void onError(Throwable t) {
System.out.println("WebSocket 连接出现错误:" + t.getMessage());
}
}