两者的作用和区别
作用:使得前后端可以随时地相互沟通。什么是互相沟通呢?像网络请求这种就是客户端向服务端的单向的沟通,当然,网络请求也可以实现双向的沟通,比如ajax 轮询
,就是浏览器开个定时器不断的发送请求来了解后端数据库中数据是否变化,但是这个性能和方式好像不太好。
区别:看来自socket.io
官网的一句话。
简单理解就是,socket.io
主要是基于webSocket
实现的,然后做了一些封装和优化吧,嗯。下面直接用两个聊天的案例来带你掌握webSocket
和socketIo
。
webSocket的使用(html+nodeJs)
就我当前学到的,做聊天的话,webSocket
主要做群聊吧,只要连接了就能接到消息。这个依赖于一个第三方包,所以需要先安装,yarn add ws
,我安装的版本是8.12.1
服务端代码。这里采用nodeJS
来编写一个webSocket
服务,代码如下:
const websocket=require("ws")
const server=new websocket.Server({port:6688},()=>{
console.log('websocketServer is running in ws://localhost:6688');
})
server.on("connection",(Ws)=>{ //用户连接时调用
console.log('hello new user')
Ws.on("message",(data)=>{
// console.log(data),可以看到传输过来的数据转buffer了
let msg
try {
const info=JSON.parse(data.toString())
const words=info.msg
const name=info.name
msg=words&&name ?`${name}:${words}`:"消息解析失败,请联系管理员!"
} catch (err) {
msg=data.toString()
}
server.clients.forEach((user)=>{
if(user.readyState===websocket.OPEN){ // websocket.OPEN值为1,表示用户已连接且可以正常通信
user.send(msg) // 把消息发送给连接本ws服务的代码端
// user.timeout(500).send(msg) // 500ms后发送
}
})
// console.log(server.clients);
})
})
编写完后,比如该文件名为 webSocketServer.js
,我们就是在终端使用指令node webSocketServer
启动该服务即可,这样客户端那边就能连接该服务了。
前端代码。api不多,可参考代码注释
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<style>
#allmsg{
width: 300px;
height: 250px;
border: 1px solid black;
overflow: auto;
}
#txtinput{
width: 150px;
height: 40px;
}
</style>
</head>
<body>
<h2>聊天社区</h2>
请输入当前登录用户的昵称:<input type="text" id="userName">
<p style="font-size:22px;">消息框</p>
<div id="allmsg"></div><br/><br/><br/>
<input type="text" name="" id="txtinput" placeholder="按回车发送消息">
<script>
const ws=new WebSocket("ws://localhost:6688")
const txtinput=document.getElementById("txtinput")
const allmsg=document.getElementById("allmsg")
const userName=document.getElementById("userName")
let user=null
userName.onblur=(e)=>{
if(e.target.value)
user={id:Math.random()+Date.now(),name:e.target.value}
else user=null
}
txtinput.onkeyup=(e)=>{
if(e.keyCode===13) // 通知socket切换房间
{
if(!user) {alert("请输入当前登录用户的昵称!");return}
if(!txtinput.value) return
ws.send(JSON.stringify({...user,msg:txtinput.value})) // 向服务器发送消息 。ws.close() - 关闭连接
txtinput.value=""
}
}
ws.onopen=()=>{ //自己连接服务器成功时回调
ws.send("新用户加入聊天室")
}
ws.onmessage=(msg)=>{ // 接到服务器的消息时回调
allmsg.innerHTML+=`<p>${msg.data}</p>`
}
ws.onerror=(err)=>{ // 出错时回调
console.log(err);
}
ws.onclose=()=>{ // 连接关闭时回调
console.log('disconnection');
}
</script>
</body>
</html>
此时,我们就可以在该html页面open with live server
3次或者更多来开多个页签,这样就可以开始测试聊天了。效果展示如下:
chat_webSocket
socket.io的使用(html+nodeJs)
由于socket.io丰富的api,可以用它来实现群聊或者私聊。这个依赖于两个第三方包,所以需要先安装
yarn add socket.io express
,我安装的socket.io
的版本是4.6.1
服务端代码。这里采用nodeJS
来编写一个socketIO
服务,代码如下,具体使用看注释
const server=require("http").createServer(require("express")())
const io=require("socket.io")(server,{cors:true}) //创建io并允许跨域
io.on("connection",(socket)=>{ //有用户连接时回调
io.emit("msg","有新用户加入群聊室")
// io.local.emit("hello", "world"); //只向连接到当前服务器的客户端发送
// 客户端 emit("msg")时回调
socket.on("msg",(data)=>{
io.local.emit("msg",data) // 把消息发送给所有订阅了msg的用户
//socket.emit("msg",data) // 把消息发送给订阅了msg的自己
//socket.broadcast.emit("msg",data) // 把消息发给除自己外的其他订阅了msg的所有用户
})
// 利用房间发送私人消息
socket.on("privateChart",(room,data)=>{
//socket.to("房间号").emit("msg",data) // 把消息发送给已拥有房间中的指定房间内订阅了msg的除自己外的所有用户
//socket.to("房间号1").to("房间号2").emit("msg",data) // 也可以给多个房间发送
socket.emit("privateChart",data)
socket.to(room).emit("privateChart",data);
})
// 用来切换房间
socket.on("changeRoom",(room)=>{
//console.log(room)
if(room=="room1") {
socket.join("room1") // 添加指定房间
socket.leave("room2") // 删除指定房间
}
else{
socket.join("room2")
socket.leave("room1")
}
//console.log(socket.rooms) // 拥有的房间列表
})
socket.on("disconnect", (reason) => {
// 此事件由 Socket 实例在断开连接时触发
});
})
server.listen(8866,()=>{
console.log('socketioServer is running in http://127.0.0.1:8866')
})
编写完后,比如该文件名为 socketIoServer.js
,我们就是在终端使用指令node socketIoServer
启动该服务即可,这样客户端那边就能连接该服务了。
前端代码如下,用到的api也不多,后端那边可能会多一点,具体使用看注释
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
<style>
#groupMsg,#privateMsg {
width: 300px;
height: 250px;
border: 1px solid black;
overflow: auto;
}
#groupInput,#privateInput {
width: 150px;
height: 40px;
}
</style>
</head>
<body>
<h2>聊天社区</h2>
<h3>群聊房间</h3>
<div id="groupMsg"></div>
<br />
<input type="text" name="groupInput" id="groupInput" placeholder="按回车发送群消息" />
<h3>私聊房间</h3>
<div id="privateMsg"></div>
<br />
<span>请选择您的聊天房间(相同房间的人才可聊天):</span>
<input type="radio" name="room" id="room1" value="room1" /> 房间1
<input type="radio" name="room" id="room2" value="room2" /> 房间2<br/><br/><br/>
<input type="text" name="privateInput" id="privateInput" placeholder="按回车发送私人消息" />
<script src="/socket.io.js">
// 该文件在服务端安装的 socket.io 包 的 client-dist 目录下,复制过来引入
</script>
<script>
//与服务器建立连接
// const socket = io('http://localhost:8866/')
const socket=io.connect("http://localhost:8866/")
const groupInput = document.getElementById('groupInput')
const groupMsg = document.getElementById('groupMsg')
const privateInput = document.getElementById('privateInput')
const privateMsg = document.getElementById('privateMsg')
const room1 = document.getElementById('room1')
const room2 = document.getElementById('room2')
groupInput.onkeyup = (e) => {
if (e.keyCode === 13) {
if(!groupInput.value) return
socket.emit('msg', groupInput.value)
groupInput.value = ''
}
}
privateInput.onkeyup = (e) => {
if (e.keyCode === 13) { // 按回车发送消息
if(!room1.checked && !room2.checked) {alert("请选择私聊的房间");return}
if(!privateInput.value) return
// 发送私人消息,第二个参数与后端约定传递房间号,之后的参数就都是数据了
socket.emit('privateChart', room1.checked?"room1":"room2", privateInput.value)
//groupMsg.innerHTML+=`<p>${ groupInput.value}</p>`
privateInput.value = ''
}
}
room1.onchange=(e)=>{ // 通知socket切换房间
socket.emit("changeRoom","room1")
}
room2.onchange=(e)=>{ // 通知socket切换房间
socket.emit("changeRoom","room2")
}
socket.on('msg', (data) => {
// 订阅服务器发送到'msg'处的消息
groupMsg.innerHTML += `<p>${data}</p>`
})
socket.on('privateChart', (data) => {
privateMsg.innerHTML += `<p>${data}</p>`
})
socket.on('connect', () => { // 连接成功后回调
})
socket.on('disconnect', (reason) => { // 连接断开时回调
})
</script>
</body>
</html>
此时,我们就可以在该html页面open with live server
3次或者更多来开多个页签,这样就可以开始测试聊天了。然后要注意的是私人房间那里不要都选同一个房间。效果展示如下:
chat_socketIo