长连接(socket)和短连接(ajax)。
长连接不存在跨域问题。
http协议不支持长连接。
实现socket的三种方式:
- net,node的内置模块
- socket.io
兼容性好,但是要先引入 - websocket
websocket是h5新增,低版本浏览器不兼容。
长连接的使用场景:
- 实时刷新
如果前端使用轮询,那么前端和服务端都要耗费资源,如果使用socket长连接,那么就只需服务端发送就可以了。 - 服务器端发起数据
ajax是前端主动往后端发送消息,后端无法主动往前端发送消息(服务器主动推送消息)。
socket的步骤
前后端的连接
1、搭建socket服务器
2、 前端进行连接
数据交互
3、 前端主动发送数据
4、后端主动发送数据
前后端断开的处理
5、断开连接
1、net模块
服务端
const net = require('net')
const server = new net.createServer()
let clients = {}
let clientName = 0
server.on('connection', (client) => {
client.name = ++clientName
clients[client.name] = client
client.on('data', (msg) => {
// console.log('客户端传来:' + msg);
broadcast(client, msg.toString())
})
client.on('error', (e) => {
console.log('client error' + e);
client.end()
})
client.on('close', (data) => {
delete clients[client.name]
console.log(client.name + ' 下线了');
})
})
function broadcast(client, msg) {
for (var key in clients) {
clients[key].write(client.name + ' 说:' + msg)
}
}
server.listen(9000)
前端
var net = require('net')
const readline = require('readline')
var port = 9000
var host = '127.0.0.1'
var socket = new net.Socket()
socket.setEncoding = 'UTF-8'
socket.connect(port, host, () => {
socket.write('hello.')
})
socket.on('data', (msg) => {
console.log(msg.toString())
say()
})
socket.on('error', function (err) {
console.log('error' + err);
})
socket.on('close', function () {
console.log('connection closeed');
})
const r1 = readline.createInterface({
input: process.stdin,
output: process.stdout
})
function say() {
r1.question('请输入:', (inputMsg) => {
if (inputMsg != 'bye') {
socket.write(inputMsg + '\n')
} else {
socket.destroy()
r1.close()
}
})
}
2、socket.io
使用自定义的事件的监听和触发机制
先下载
npm install socket.io
服务端
var express = require('express');
var app = express();
var server = require('http').Server(app);// 通过http创建一个服务器
var ws = require('socket.io')(server);//将socket 服务器和express 进行结合,通过express启动socket.io
// 静态文件目录
app.use(express.static(__dirname + '/client'))
// 客户端连接
ws.on('connection', function (client) {
client.emit('hehe','欢迎光临')//触发事件(触发hehe事件,在前端监听hehe事件)
client.on('haha',(msg)=>{//绑定(监听)事件,在前端触发haha事件
console.log('haha'+msg)
})
});
// 允许所有端口访问
server.listen(8081, '0.0.0.0');
前端
引入socket.io
var socket = io.connect('http://localhost:8081');//连接服务器
socket.on('hehe', function(msg){
console.log('hehe'+msg)
})
socket.emit('haha','我来了')
3、websocket
先下载包
npm install ws
服务端
const WebSocket=require('ws');// 创建websocket服务器
const ws=new WebSocket.Server({port:8080},()=>{
console.log("socket start!")
})
let clients=[];//存储每个与服务器连接的客户端,用于群发
// 与前端建立连接
ws.on('connection',(client)=>{
// 将每个与服务器链接上的client对象push到clients数组中
clients.push(client);
client.send('欢迎光临hello');//数据传输只能传字符串,传对象先JSON.stringify
client.on('message',(msg)=>{//监听message,前端发数据过来时触发
console.log(msg);
if(msg.indexOf("广播")!=-1){
sendAll(msg);
}
})
client.on('close',(msg)=>{
console.log("前端主动断开了链接")
})
})
// 群发
function sendAll(msg){
for (let i = 0; i < clients.length; i++) {
clients[i].send(msg);
}
}
前端
浏览器或nw自带,不需引入
// 创建websocket服务器
const ws=new WebSocket('ws://192.168.31.180:8080/');//服务器地址(或ws://localhost:8080/),使用的协议是ws协议
// 监听与服务器建立连接
ws.onopen=function(){
console.log('服务器已经连接')
}
// 监听message,接收来自服务端的数据
ws.onmessage=(msg)=>{
console.log(msg.data)
}
// 监听服务器的关闭
ws.onclose=()=>{
console.log('服务器关闭')
}
function sendMessage(){
let msg=document.getElementById("msg").value;
document.getElementById("msg").value='';
ws.send(msg)
}
在前端打印websocket实例
close方法用于在前端手动断开连接。