1、webSocket长连接
应用场景:站内信,会员到期提醒等。webSocket只能传输字符串,使用node向前端发送数据的时候,使用JSON.stringify()转换一下数据格式。在node服务端使用ws模块来搭建webSocket服务,webSocket服务可以和express服务共存,可以写在同一个server服务文件里,前提是占用不同的接口。
2、实现socket的方法:
- net
- websocket 在html5新增的,使用简单,低版本浏览器不兼容。
- socket.io 兼容性最好,比较麻烦
3、实现步骤:
- 前后端连接
- 1、后端搭载socket服务器 new WebSocket.server({port: 8080}, ()=>{})
ws.on(‘connection’) - 2、前端进行连接 new WebSocket(‘ws:localhost:8080’)
ws.onOpen()
- 数据交互
- 1、前端主动发送数据 ws.onmessage=()=>{}监听
ws.send()发送数据 - 2、后端主动发送数据 ws.on(‘message’, ()=>{})监听
- 断开连接
- 1、后端断开ws.on(‘close’)
- 2、前端断开ws.onClose()
4、具体代码实现步骤:
// 前端
import React, {useEffect} from 'react';
export default function WebSockets(){
const ws=new WebSocket('ws://localhost:8080');
useEffect(()=>{
ws.onopen=()=>{
console.log('webSocket服务已连接')
}
ws.onmessage=(msg)=>{
console.log('来自后端的数据'+msg.data)
}
ws.onclose=()=>{
console.log('后端主动关闭')
}
})
const handleClickSend=()=>{
ws.send('hellos');
}
return (
<div>
<h2>WebSocket页面</h2>
<button onClick={handleClickSend}>点击向websocket发送数据</button>
</div>
)
}
// 后端
const WebSocket=require('ws');
const ws=new WebSocket.Server({port: 8080}, ()=>{
console.log('webSocket 运行在8080端口')
})
ws.on('connection', (client)=>{
client.send('欢迎光临'); // 只能传输字符串
client.on('message', (msg)=>{
console.log('收到前端传递的数据'+msg);
});
client.on('close', (msg)=>{
console.log('前端主动断开连接');
});
})
如果想做某种聊天工具,需要收到前端数据后发送给所有用户,可以使用广播来完成。
具体后端实现:
const WebSocket=require('ws');
const ws=new WebSocket.Server({port: 8080}, ()=>{
console.log('webSocket 运行在8080端口')
})
const clients=[];
ws.on('connection', (client)=>{
clients.push(client)
client.send('欢迎光临'); // 只能传输字符串
client.on('message', (msg)=>{
console.log('收到前端传递的数据'+msg);
sendAll(msg);
});
client.on('close', (msg)=>{
console.log('前端主动断开连接');
});
})
// 广播
function sendAll(msg){
for(let i=0; i<clients.length;i++){
clients[i].send(msg);
}
}
5、注意:webSocket是不存在跨域的,所以,除了正规的解决跨域方式之外,websocket长连接是解决跨域的一种方法。
6、使用socket.io进行长连接
socket.io主要思想就是传参数,需要先自定义事件,假如想要在服务端传递数据给浏览器,需要先使用emit自定义事件auto(该自定义事件名称随便起,前提是前后端要对应上),在浏览器中触发该事件auto,来获得数据。同理浏览器想要传递数据给服务器,需要先使用emit自定义事件getData,在node服务触发该自定义事件getData。
- 在服务端主要使用socket.io模块,安装该模块,服务端代码如下:
const express=require('express');
const app=express();
const server=require('http').createServer(app);
const ws=require('socket.io')(server);
ws.on('connection', (client)=>{
client.emit('auto','我是参数');
client.on('getData', (meg)=>{
console.log(meg+'从浏览器发过来的数据')
})
})
server.listen(8081, '0.0.0.0');
- 在前端主要使用socket.io-client插件来接收,前端代码如下:
import React, {useEffect} from 'react';
import io from 'socket.io-client';
export default function SocketIo(){
const socket=io.connect('http://localhost:8081');
useEffect(()=>{
socket.on('auto', (msg)=>{
console.log('socket'+msg)
});
})
const handleClickSend=()=>{
socket.emit('getData', '浏览器数据666');
}
return (
<div>
<h2>socket.io页面</h2>
<button onClick={handleClickSend}>点击向websocket发送数据</button>
</div>
)
}