web通讯的四种方式,常规轮询、长轮询(comet)、长连接(SSE)、WebSocket
常规轮询
- 客户端
const axios = require("axios")
setInterval(function(){
if(data.data){
clearInterval(dataSet)
return
}
axios({
method: 'GET',
url: 'api/users/list',
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
},1000)
- 服务端
const koa = require('koa')
const koaRouter = require('@koa/router')
const app = new koa()
const userRouter = new koaRouter({ prefix: '/users' })
userRouter.get('/list', async (ctx, next) => {
console.log(ctx.header);
async function delay(time) {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
let num = Math.floor(Math.random() * 100)
if (num < 30) {
ctx.body = [
{ name: 'why', age: 18, score: 99 },
{ name: 'kobe', age: 30, score: 60 },
{ name: 'wi', age: 90, score: 23 },
]
} else {
ctx.body = ''
}
}, time)
})
}
await delay(300)
}),
app.use(userRouter.routes())
app.listen('9000', '0.0.0.0', () => {
console.log('api服务器启动');
})
长轮询
- 客户端
const axios = require("axios")
async function subscribe() {
let response = await axios({
method: 'GET',
url: 'api/users/list',
})
if (response.status == 502) {
// 状态 502 是连接超时错误,
// 连接挂起时间过长时可能会发生,
// 远程服务器或代理会关闭它
// 让我们重新连接
await subscribe();
} else if (response.status != 200) {
// 一个 error —— 让我们显示它
console.log(response.statusText);
// 一秒后重新连接
await new Promise(resolve => setTimeout(resolve, 1000));
await subscribe();
} else {
// 获取并显示消息
let message = await response.data;
console.log(message);
// 再次调用 subscribe() 以获取下一条消息
await subscribe();
}
}
subscribe();
长连接(SSE)
一般提供timeout
WebSocket
允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
- 对于WebSocket是通过tcp和http通行的全双工通信
- 请求:在进行
websocket通信时,首先时tcp链接,在请求头里面会携带Connection:keep-alive,Upgrade(Upgrade是请求网络升级)和Upgrade:websocket(升级为websocket), - 响应:在进行
websocket通信时,会在响应头里面携带Upgrade:websocket和Connection:Upgrade
tcp 首先tcp协议是不能通过浏览器通信的,只能通过node通信
第三方库的使用
websocket-node
- 客户端
var W3CWebSocket = require('websocket').w3cwebsocket;
var client = new W3CWebSocket('ws://192.168.31.220:8080/');
/**
* readyState
* 0,new是为0 链接还没有建立(正在建立)
* 1,链接建立成功
* 2,链接正在关闭
* 3,链接已经关闭
*/
console.log(client.readyState);
client.onerror = function() {
console.log('Connection Error');
};
client.onopen = function() {
console.log(client.readyState,client.OPEN);
console.log('WebSocket Client Connected');
function sendNumber() {
if (client.readyState === client.OPEN) {
var number = Math.round(Math.random() * 0xFFFFFF);
console.log(number)
client.send(number.toString());
// setTimeout(sendNumber, 1000);
}
}
sendNumber();
};
client.onclose = function() {
console.log('echo-protocol Client Closed');
};
client.onmessage = function(e) {
console.log(e)
if (typeof e.data === 'string') {
console.log("Received: '" + e.data + "'");
}
};
- 服务端
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function (request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(200);
response.end();
});
server.listen(8080, function () {
console.log((new Date()) + ' Server is listening on port 8080');
});
const wsServer = new WebSocketServer({
httpServer: server,
autoAcceptConnections: false
});
let connectArr = []
wsServer.on('request', function (request) {
var connection = request.accept();
connectArr.push(connection)
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function (message) {
console.log(message)
for (let index = 0; index < connectArr.length; index++) {
connectArr[index].send(message.utf8Data)
}
});
connection.on('close', function (reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
socket.io && koa
- 客户端
const { io } = require("socket.io-client");
const socket = io.connect("http://192.168.31.220:3000");
(()=>{
socket.emit("request", "world");
console.log('emit-connection')
})()
socket.on("connect", () => {
console.log(socket.id); // x8WIv7-mJelg7on_ALbx
});
socket.on("disconnect", () => {
console.log(socket.id); // undefined
});
- 服务端
const koa = require('koa')
const app = new koa()
const server = require('http').createServer(app.callback());
const io = require('socket.io')(server, {
cors: {
origin: "*"
}
});
io.on('connection', (socket) => {
socket.on('request', function (data) {
console.log('data' + data)
})
console.log('已经链接')
});
server.listen(3000, function () {
console.log('FUWUQIDONG')
});
萌新交流,互相学习,勿喷