# 前后端通信
## 1、websocket
?
? `websocket :長連接,雙向的。node搭建的websocket服務器,推送信息給客戶端瀏覽器`
* 前端
? ```html
? ? <!-- websocket.html -->
? ? <div id="clock"></div>
? ? <script>
? ? ? let clockDiv = document.getElementById('clock')
? ? ? let socket = new WebSocket('ws://localhost:9999')
? ? ? //當連接成功之后就會執行回調函數
? ? ? socket.onopen = function() {
? ? ? ? console.log('客戶端連接成功')
? ? ? ? //再向服務 器發送一個消息
? ? ? ? socket.send('hello') //客戶端發的消息內容 為hello
? ? ? }
? ? ? //綁定事件是用加屬性的方式
? ? ? socket.onmessage = function(event) {
? ? ? ? clockDiv.innerHTML = event.data
? ? ? ? console.log('收到服務器端的響應', event.data)
? ? ? }
? ? ? window.onload=function(){
? ? ? ? clockDiv.addEventListener('click',()=>{
? ? ? ? ? socket.send('clockDiv點擊事件')
? ? ? ? })
? ? ? }
? ? </script>
? ```
* 后端
? ```js
? ? // websocket.js
? ? /**
? ? * 依賴包
? ? *? npm i express ws -S
? ? */
? ? let express = require('express')
? ? let app = express()
? ? app.use(express.static(__dirname))
? ? //http服務器
? ? app.listen(3000)
? ? let WebSocketServer = require('ws').Server
? ? //用ws模塊啟動一個websocket服務器,監聽了9999端口
? ? let wsServer = new WebSocketServer({ port: 9999 })
? ? //監聽客戶端的連接請求 當客戶端連接服務器的時候,就會觸發connection事件
? ? //socket代表一個客戶端,不是所有客戶端共享的,而是每個客戶端都有一個socket
? ? wsServer.on('connection', function(socket) {
? ? ? //每一個socket都有一個唯一的ID屬性
? ? ? console.log(socket)
? ? ? console.log('客戶端連接成功')
? ? ?
? ? ? //監聽對方發過來的消息
? ? ? socket.on('message', function(message) {
? ? ? ? console.log('接收到客戶端的消息', message)
? ? ? ? socket.send('服務器回應:' + message)
? ? ? })
? ? ? setTimeout(()=>{
? ? ? socket.send('內容更新了:')
? ? ? },5000)
? ? })
? ```
## 2、Server-Sent Events(簡稱SSE)/EventSource
? `只是從服務器端往客戶端單向傳輸數據,感覺就隔幾秒發送一個get請求獲取數據`
* 前端
? ```html
? ? <!-- sse.html -->
? ? <div id="clok"></div>
? <script type="text/javascript">
? ? ? if ('EventSource' in window) {
? ? ? ? var source = new EventSource('http://127.0.0.1:8844/stream');
? ? ? ? var sseEl = document.getElementById('clok');
? ? ? ? source.addEventListener('open', function (event) {
? ? ? ? ? sseEl.innerHTML += '<p>Connection open ...</p>';
? ? ? ? }, false);
? ? ? ? source.addEventListener('message', function (event) {
? ? ? ? ? sseEl.innerHTML += ('<p>Ping: ' + event.data + '</p>');
? ? ? ? }, false);
? ? ? ? source.addEventListener('error', function (event) {
? ? ? ? ? sseEl.innerHTML += '<p>Connection close.</p>';
? ? ? ? }, false);
? ? ? ? source.addEventListener('connecttime', function (event) {
? ? ? ? ? ? sseEl.innerHTML += ('<p>Start time: ' + event.data + '</p>');
? ? ? ? ? }, false);
? ? ? ? // source.close();
? ? ? ? source.addEventListener('foo', function (event) {
? ? ? ? ? var data = event.data;
? ? ? ? ? // handle message
? ? ? ? }, false);
? ? ? }
? </script>
? ```
* 后端
? ```js
? ? // sse.js
? ? /**
? ? * 依賴包 npm i http -S
? ? */
? ? var http = require("http");
? ? http.createServer(function (req, res) {
? ? ? var fileName = "." + req.url;
? ? ? if (fileName === "./stream") {
? ? ? ? res.writeHead(200, {
? ? ? ? ? "Content-Type":"text/event-stream",
? ? ? ? ? "Cache-Control":"no-cache",
? ? ? ? ? "Connection":"keep-alive",
? ? ? ? ? "Access-Control-Allow-Origin": '*',
? ? ? ? });
? ? ? ? res.write("retry: 10000\n");
? ? ? ? res.write("event: connecttime\n");
? ? ? ? res.write(`data: ${(new Date())}\n\n`);
? ? ? ? res.write(`data: ${(new Date())}\n\n`);
? ? ? ? interval = setInterval(function () {
? ? ? ? ? res.write(`data:數據內容更新了1\n\n`);
? ? ? ? }, 1000);
? ? ? ? req.connection.addListener("close", function () {
? ? ? ? ? clearInterval(interval);
? ? ? ? }, false);
? ? ? }
? ? }).listen(8844, "127.0.0.1");
? ```
## 3、
> 參考資料
* [Web 實時推送技術的總結](https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651556073&idx=1&sn=7009b6f2c95e3e48254964f43e838d9b&chksm=80255f28b752d63e89e5e96b3d462ea025bb7a4cc03783e5c8f8c86fcfdcb51b8d3c901035b8&mpshare=1&scene=1&srcid=#rd)
* [Server-Sent Events 教程](http://www.ruanyifeng.com/blog/2017/05/server-sent_events.html)