轮询概念:是指不管服务器端有没有更新,客户端(通常是指浏览器)都定时的发送请求进行查询。不管结果如何,客户端处理完第一次请求后到下一个定时时间点将继续下一轮的轮询。
**缺点:**当客户端以固定频率向服务器发起请求的时候,服务器端的数据可能并没有更新,这样会带来很多无谓的网络传输。当轮询时间过长则无法接收到更新数据。
**优点:**web应用场景可作为即时通讯类的解决方案,客户端在每次固定时间自动发起请求可做到实时更新数据。操作简单,无需做更多更改。
Example:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实时获取时间title>
head>
<body>
<script>
//每隔一秒钟客户端发起一次请求以达到实时更新
setInterval(function(){
var xhr = new XMLHttpRequest();
xhr.open('GET','/polling');
xhr.onload=function(e){
document.querySelector('body').innerHTML='时间:'+e.target.response
}
xhr.send()
},1000)
script>
body>
html>
const Koa = require('koa')
const Router = require('koa-router')
const moment = require('moment') //格式化日期轻量级js库,返回一个格式化日期的虚拟属性
const serve = require('koa-static')
const app = new Koa();
const router = new Router()
app.use(serve(__dirname + '/static'))
router.get('/polling',(ctx)=>{
ctx.body = getDate()
})
function getDate(){
return moment().format('YYYY-MM-DD hh:mm:ss')
}
app.use(router.routes()).use(router.allowedMethods())
app.listen(9000,()=>{
console.log('服务启动成功')
})
服务器推送技术
服务器端与浏览器端之间的通讯协议,是基于纯文本的简单协议。服务器端的响应的内容类型content-type是"text/event-stream"。浏览器端使用的EventSource对象.
Example:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SSEtitle>
head>
<body>
时间:
<script>
var sse = new EventSource('/sse')
sse.addEventListener('open',(e)=>{//初始化页面执行一次
document.querySelector('body').innerHTML = e.data;
})
sse.addEventListener('message',(e)=>{ //后续接收推送
document.querySelector('body').innerHTML = e.data
})
script>
body>
html>
const http = require('http')
const fs = require('fs')
const moment = require('moment')
const server = http.createServer((req,res)=>{
if(req.url=='/sse'){
//sse - 服务端推送到客户端
res.writeHead(200,{'content-type':'text/event-stream'}) //发送流的请求头信息
// \n\n表示结束一条信息
setInterval(() => {
res.write(`data:${getDate()}\n\n`)
}, 1000);
}else{
res.setHeader('content-type','text/html')
let readStream = fs.createReadStream(__dirname+'/static/index.html')
readStream.pipe(res)
}
})
function getDate(){
return moment().format('YYYY-MM-DD hh:mm:ss')
}
server.listen(3000,()=>{
console.log('service started successfully');
})
概念: TCP
协议连接的全双工通讯协议,标识符ws
。标识符是wss
的连接建立在TLS
协议之上。如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kpdPGxHg-1587637386273)(/Users/liuyan/Desktop/websocket.png)]
浏览器通过 JavaScript 向服务器发出建立ws协议连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。当获取 WebSocket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。
特点:
建立在TCP协议之上的持久连接。只需要一次http握手。没有同源限制。标识符是ws
。可以发文本也可以发二进制数据。双工通信。
Example:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>实时获取时间title>
head>
<body>
时间日期:
<div class="txt">div>
<button onclick="hanldStart()">开始button>
<button onclick="hanldStop()">停止button>
<script>
var txt = document.querySelector('.txt') //显示位置
const websocket = new WebSocket('ws://localhost:3000')
websocket.addEventListener('open', (e) => {
console.log('open', e)
})
websocket.addEventListener('message', (e) => {
txt.innerHTML = e.data
})
websocket.addEventListener('error', (e) => {
console.log('error', e)
})
function hanldStart() {
websocket.send('start')
}
function hanldStop() {
websocket.send('stop')
}
script>
body>
html>
const Websocket = require('ws')
const moment = require('moment')
const ws = new Websocket.Server({ port: 3000 })
var is = false
ws.on('connection', (ws) => {
ws.on('message', (message) => {
if (message === 'start') {
is = true
}
if (message === 'stop') {
is = false
}
setInterval(() => {
if (is) {
ws.send(getData())
}
}, 1000)
})
})
function getData() {
return moment().format('YYYY-MM-DD hh:mm:ss')
}
方法&事件 | 描述 |
---|---|
open | 连接建立时触发 |
message | 客户端接收服务端数据时触发 |
error | 通信发生错误时触发 |
close | 连接关闭时触发 |
Socket.send() | 使用连接发送数据 |
Socket.close() | 关闭连接 |
查看代码:https://github.com/XiaoYanY/–websocket-koa