小制作手工废物利用,温州企业网站排名优化,网站源码带手机版,建立网站建站程序个人学习记录#xff0c;欢迎指正 1.轮询
1.1 轮询的形式 短连接轮询 前端每隔一段时间向服务端发起一次Http请求来获取数据。 const shortPolling () {
const intervalHandler setInterval(() {fetch(/xxx/yyy).then(response response.json()).then(respo… 个人学习记录欢迎指正 1.轮询
1.1 轮询的形式 短连接轮询 前端每隔一段时间向服务端发起一次Http请求来获取数据。 const shortPolling () {
const intervalHandler setInterval(() {fetch(/xxx/yyy).then(response response.json()).then(response {/* 自定义短轮询成功标记 */if(response?.code 1) {/* 自定义工作代码 *//* 结束短轮询 */ clearInterval(intervalHandler) } })
}, 5000);
}长连接轮询 前端向服务端发起一次Http请求当接收到响应体时重新发起请求来获取数据。 const longPolling () {fetch(/xxx/yyy).then(response response.json()).then(data {/* 自定义工作代码 *//* 继续长轮询 */longPolling();})
}1.2 轮询的实现 基于Ajax技术轮询 在1中已经举了关于基于ajax技术实现长轮询和短轮询的例子 基于Iframe的轮询 古老的轮询方式需要装填数据到jspphp等形式文档中没有实现前后端分离开发。 插入 前端在页面中插入一个隐藏的iframeiframe的src设置为后端接口地址。 填充 接口返回数据格式为html服务端用传统web开发形式向html中插入数据例如phpjsp。 通信 返回的html在iframe中运行通过postMessage与原页面进行通信。 轮询 原页面收到数据后重新加载iframe进行下次轮询可以根据策略进行长轮询或短轮询。 基于Jsonp的轮询 古老的轮询方式请求失败时无法通过删除标签关闭连接。 插入 前端在页面中插入一个script标签src设置为后端接口地址参数上拼接回调函数名称当接收到数据后调用之。 填充 接口返回可执行脚本脚本最后调用回调函数便于通知数据已接收到。 通信 通过回调函数通信。 轮询 接收到数据后前端重新发起Jsonp轮询删除标签后插入新的标签继续请求根据需求进行长轮询或短轮询。 2.iframe长连接 原理 例如使用http1.x进行通信服务端在发送响应信息后不关闭信道在nodejs中即不写 res.end()每隔一段时间向客户端发送一次消息。这个可以利用服务端持续向iframe输入文档实现。如果使用fetchxhr那么无法直接实现它们只能支持接收一次消息。目前一般不使用iframe这种古老做法 前端代码 html
headmeta charsetUTF-8 /
/head
bodydiv iddisplay-div/divbutton onclickhandleStartConnect()开始连接/buttonbutton onclickhandleStopConnect()断开连接/buttonscript typetext/javascript// 开始连接const handleStartConnect () {const iframe document.createElement(iframe);iframe.id iframe-connector;iframe.src /iframeLongConnection;iframe.style.display none;document.body.append(iframe);};// 断开连接const handleStopConnect () document.querySelector(#iframe-connector).remove();// 收集长连接信息 window.addEventListener(message, (event) {document.querySelector(#display-div).innerHTML event.data;});/script
/body
/html服务器代码 let fs require(fs);// 服务器基本服务
const read (path, res) {
// 支持读取html和js
fs.readFile(path, (err, data) {if (err) console.log(err);else {res.writeHead(200, {Content-Type:path.slice(-2, path.length) js? text/javascript: text/html,});res.write(data);res.end();}
});
};// 输入到iframe中的模板
const getTemplate () {
const template script typetext/javascriptwindow.parent.postMessage(new Date().toLocaleTimeString(), http://localhost:3000/index.html);/script
;
return template;
};// 服务端定时器维持长连接
const circulate (res) {
res.writeHead(200, { Content-Type: text/html });
setInterval(() {res.write(getTemplate());
}, 1000);
};require(http)
.createServer(function (req, res) {// 处理图标if (req.url /favicon.ico) res.end();// 长连接测试else if (req.url /iframeLongConnection) circulate(res);// 服务器基本服务else read(. req.url, res);
})
.listen(3000, function (err) {if (err) console.log(err);else console.log(运行成功);
});4.Websocket长连接
4.1 Websocket实现 4.1 综述 技术综述 websocket是协议是对http协议的升级。 websocket基于TCP协议也是使用80端口。 功能特点 前端实现简单只需要建立连接监听屈指可数的几个事件。支持全双工通信。服务端和客户端可以互相发送消息。不局限于web端。其它终端设备或应用程序也可以使用该协议。 4.2 web端Websocket事件和方法 事件描述open连接建立close连接关闭error发生错误message接收信息 实例方法描述send发送消息close关闭连接 4.3 服务端Websocket的事件和方法 服务端实现websocket通常采用第三方库不同的第三方库对方法和事件的规定各不相同在此不做具体介绍。 4.4 客户端代码实现 html
headmeta charsetUTF-8 /
/head
bodybutton onclickhandleBuild()建立连接/buttonbutton onclicksocket.close()断开连接/buttonbutton onclicksocket.send(123)发送一条消息/buttonscript typetext/javascriptlet socket null;// 连接相关事件监听函数const handleMessage (event) alert(event.data);const handleOpen () alert(连接成功);const handleError () alert(连接错误);const handleClose () {alert(连接关闭);socket.removeEventListener(open, handleOpen);socket.removeEventListener(close, handleClose);socket.removeEventListener(error, handleError);socket.removeEventListener(message, handleMessage);};// 建立连接const handleBuild () {socket new WebSocket(ws://localhost:3001/testSocket);socket.addEventListener(open, handleOpen);socket.addEventListener(close, handleClose);socket.addEventListener(error, handleError);socket.addEventListener(message, handleMessage);};// 关闭连接const handleDestroy () socket.close();// 发送消息const sendMessage (message) socket.send(JSON.stringify(message));/script
/body
/html4.5 服务端代码实现 const fs require(fs);
const ws require(nodejs-websocket);// 基本读写服务
const read (path, res) {// 支持读取html和jsfs.readFile(path, (err, data) {if (err) console.log(err);else {res.writeHead(200, {Content-Type:path.slice(-2, path.length) js? text/javascript: text/html,});res.write(data);res.end();}});
};require(http).createServer(function (req, res) {// 处理图标if (req.url /favicon.ico) res.end();else read(. req.url, res);}).listen(3000, function (err) {if (err) console.log(err);else console.log(运行成功);});const wsServer ws.createServer((conn) {// 接收信息conn.on(text, (text) conn.sendText(服务端已收到信息您的信息是${text}));// 连接错误conn.on(error, () console.log(连接错误));// 连接关闭conn.on(close, () console.log(连接断开));
});wsServer.on(connection, () console.log(新连接建立));
wsServer.listen(3001);4.2 Websocket建立与销毁 Http握手 Websocket连接建立需要Http1.1或以上版本的get方法握手这个过程在浏览器调试栏中无法抓包得到只能抓包分析Websocket协议。 在前端和后端实现websocket时这个过程和配置对于开发者是无感知的。 请求头 字段取值含义是否必设置Connectionupgrade希望协议升级必须Upgradewebsocket协议应该升级到websocket协议必须Sec-Websocket-Key经过base64编码的16字节随机值必须Sec-WebSocket-Version版本值websocket版本必须Sec-WebSocket-Protocol子协议名称websocket通信时需要的子协议非必须Sec-WebSocket-Extensions扩展协议名称websocket通信时的扩展协议非必须 响应头 字段取值含义是否必设置Sec-WebSocket-AcceptSHA-1哈希值是否支持websocket协议必须Sec-WebSocket-Versionwebsocket版本选择支持的websocket版本必须Sec-WebSocket-Protocol子协议名称选择支持的子协议非必须Sec-WebSocket-Extensions扩展协议名称选择支持的扩展协议名称非必须 响应状态码 响应状态码为101时表示可以使用websocket协议 Sec-Websocket-Key验证 验证过程类似于加密解密。 客户端传给服务端Sec-Websocket-Key服务端将这个key和一个规定的并且是固定的Websocket魔数字符串拼接。之后服务端将这个拼接的字符串输入SHA-1哈希算法得到哈希值。最后服务端将哈希值返回给客户端客户端用同样方式解密来判断服务端是否支持websocket协议。 挥手 服务端发出关闭连接的消息或客户端发来关闭连接的消息后将关闭websocket连接 5.SSE长连接 5.1 综述 技术综述 SSE是一种基于Http协议的技术不是一种新的协议。 功能特点 前端需要实现代码不多。由于只是使用Http协议因此前后端的配置会比使用Websocket协议简单些。由于只是使用Http协议因此只能服务端向前端推送消息相比Websocket协议的长连接像阉割版。 性能限制 同一个浏览器同一个域的Http连接最多支持并发6个如果长时间用SSE技术保持长连接会降低该域的并发连接数量。 5.2 客户端代码实现 htmlheadmeta charsetUTF-8 //headbodydiv idmessage-collector/divbutton onclickhandleBuild()建立连接/buttonbutton onclickSSETarget.close()关闭连接/buttonscript typetext/javascriptlet SSETarget null;const handleBuild () {SSETarget new EventSource(http://localhost:3002/sseStream);SSETarget.addEventListener(open, () alert(数据链路可以通信));SSETarget.addEventListener(error, () alert(数据链路发生错误));// 接收数据SSETarget.addEventListener(message,(event) (document.querySelector(#message-collector).innerHTML event.data));// 监听服务端配置的自定义事件SSETarget.addEventListener(testEvent, (event) console.log(event));};/script/body
/html5.3 服务端代码实现 响应类型 保证返回的数据类型是 text/event-stream。响应数据结构 保证换行返回保证数据是 xxx: yyy形式返回xxx可取值有 event, data, id等等分别表示描述事件的响应描述数据内容的响应描述数据id的响应。 // 服务器基本读写服务
const read (path, res) {// 支持读取html和jsrequire(fs).readFile(path, (err, data) {if (err) console.log(err);else {res.writeHead(200, {Content-Type:path.slice(-2, path.length) js? text/javascript: text/html,});res.write(data);res.end();}});
};require(http).createServer((req, res) {// SSE技术服务端简单实现if (req.url /sseStream) {res.writeHead(200, {// 必须得返回类型Content-Type: text/event-stream});res.write(retry: 10000\n);// 自定义一个事件res.write(event: testEvent\n);// 在该自定义事件下发送信息给客户端res.write(id: testId\n\n);res.write(data: new Date() \n\n);interval setInterval(() {res.write(event: message\n);res.write(id: messageId\n\n);res.write(data: new Date() \n\n);}, 1000);req.connection.addListener(close, () clearInterval(interval), false);} // 处理图标else if (req.url /favicon.ico) res.end();// 服务器基本服务else read(. req.url, res);}).listen(3002);