Websocket 介绍
Websocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许
服务器主动发送信息给客户端。
Websocket是—种持久协议,http是非持久协议
现在很多网站都有实时推送的需求,比如聊天,客服咨询等
早期没有websocket时,通过ajax轮询,由于http请求,服务器无法给浏览器主动发送数据,因此需要浏览器定时的给服务器发送请求(比
如1s一次),服务器把最新的数据响应给浏览器。这种模式的缺点就是浪费性能和资源。

websocket是一种网络协议,允许客户端和服务端全双工的进行网络通讯,服务器可以给客户端发消息,客户端也可以给服务器发消息。
Websocket基本使用
在HTML5中,浏览器已经实现了websocket的API,直接使用即可。
WebSocket-MDN
创建Websocket对象
1 2 3 4
   | 
 
  var Socket = new Websocket(url, [protocol] );
 
  | 
WebSocket事件
| 事件 | 事件处理程序 | 描述 | 
|---|
open | Socket.onopen | 连接建立时触发 | 
message | Socket.onmessage | 客户端接收服务端数据时触发 | 
error | Socket.onerror | 通信发生错误时触发 | 
close | Socket.onclose | 连接关闭时触发 | 
Websocket方法
| 方法 | 描述 | 
|---|
Socket.send() | 使用连接发送数据 | 
Socket.close() | 关闭连接 | 
示例
一个简单的示例 index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
   | <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>WebSocket学习</title> </head> <body>     <input type="text">     <button>点我发送</button>     <div style="width: 100px;height: 100px;border:1px solid red"></div>          <script>         const input = document.querySelector("input")         const button = document.querySelector("button")         const div = document.querySelector("div")
                            const socket = new WebSocket("ws://echo.websocket.org")                           socket.addEventListener("open",()=>{             div.innerText = "连接成功"         })
                   button.addEventListener("click",()=>{             var value = input.value             socket.send(value)         })
                   socket.addEventListener("message",(e)=>{             console.log(e.data);             div.innerHTML = e.data         })
                   socket.addEventListener("close",()=>{             div.innerHTML = "断开服务"         })     </script> </body> </html>
   | 
使用nodejs开发websocket服务
我们刚刚使用了官网提供的echo服务,I接下来我们自己通过nodejs实现一个简单的websocket服务。
使用nodejs开发websocket需要依赖一个第三方包。Nodejs Websocket
项目搭建
安装 nodejs-websocket
开发服务程序
使用 app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   |  const ws = require("nodejs-websocket")
  const port = 3000
 
  var server = ws.createServer((conn) => {     console.log("有用户连接了。。。");
           conn.on("text", (data) => {         console.log("接收到数据 " + data);                  conn.send(data)     })
           conn.on("close", () => {         console.log("用户断开连接");     })          conn.on("error", () => {         console.log("发生错误");     }) })
 
  server.listen(port, () => {     console.log("连接端口" + port); })
 
  | 
编辑 index.html
1 2 3 4
   | 
 
  const socket = new WebSocket("ws://localhost:3000")
 
  | 
示例
一个简单的聊天室
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
   | <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>WebSocket学习</title> </head> <body>     <input type="text">     <button>点我发送</button>     <div></div>
      <script>         const input = document.querySelector("input")         const button = document.querySelector("button")         const div = document.querySelector("div")         const TYPE_ENTER = 0         const TYPE_LEAVE = 1         const TYPE_MSG = 2
                                     const socket = new WebSocket("ws://localhost:3000")
                   socket.addEventListener("open", () => {             div.innerText = "连接成功"         })
                   button.addEventListener("click", () => {             var value = input.value             socket.send(value)             input.value = ""         })
                   socket.addEventListener("message", (e) => {                          var data = JSON.parse(e.data)             var dv = document.createElement("div")             dv.innerText = data.msg + "--------" + data.time             if (data.type == TYPE_ENTER) {                 dv.style.color = "green"             } else if (data.type == TYPE_LEAVE) {                 dv.style.color = "red"             } else {                 dv.style.color = "blue"             }             div.appendChild(dv)         })
                   socket.addEventListener("close", () => {             div.innerHTML = "断开服务"         })     </script> </body> </html>
   | 
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
   |  const ws = require("nodejs-websocket");
  const TYPE_ENTER = 0 const TYPE_LEAVE = 1 const TYPE_MSG = 2
  const port = 3000
 
  let count = 0
 
  var server = ws.createServer((conn) => {     console.log("有用户连接了。。。");     count++     conn.userName = `用户${count}`     
      bordercast({         type: TYPE_ENTER,         msg: `${conn.userName}进入了聊天室`,         time: new Date().toLocaleTimeString()     })
           conn.on("text", (data) => {                  bordercast({             type: TYPE_MSG,             msg: `${conn.userName}: ` +data,             time: new Date().toLocaleTimeString()         })     })
           conn.on("close", () => {         console.log("用户断开连接");         count--                  bordercast({             type: TYPE_LEAVE,             msg: `${conn.userName}离开了聊天室`,             time: new Date().toLocaleTimeString()         })     })          conn.on("error", () => {         console.log("发生错误");     }) })
 
  var bordercast = (msg)=>{          server.connections.forEach(item=>{                  item.send(JSON.stringify(msg))     }) }
 
  server.listen(port, () => {     console.log("连接端口" + port); })
 
  | 
如果使用原生的websocket进行开发,会比较麻烦,比如支持的事件太少,发送的数据只能是字符串格式的,提供的api也很少,类似于广播这种方法都没有,需要自己封装。
socket.io基本使用
socket.io
安装 socket.io
socket.emit: 表示触发某个事件 如果需要给浏览器发数据.需要触发浏览器注册某个事件
socket.on: 表示的注册某个事件 如果需要获取浏览器的数据,需要注册一个事件,等待浏览器触发
服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   | const http = require('http') const fs = require('fs') const app = http.createServer() app.on("request", (req, res) => {     fs.readFile(__dirname + '/index.html', function (err, data) {         if (err) {             res.writeHead(500)             return res.end('Error loading index.html')         }         res.writeHead(200)         res.end(data)     })
  })
  app.listen(3000, () => {     console.log("服务器启动成功"); }); const io = require("socket.io")(app)
 
 
 
  io.on("connection",socket=>{     console.log("新用户连接");               socket.on("hehe",data=>{         console.log(data);         socket.emit("send",data)     }) })
  | 
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   | <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>Document</title> </head> <body>     <script src="/socket.io/socket.io.js"></script>     <script>                           const socket = io("http://localhost:3000"); 		         socket.emit("hehe",{name:"zykj",age:18}) 		         socket.on('send',data=>{             console.log(data);         })     </script> </body> </html>
   | 
基于socket.io开发完整的聊天室
部分内容讲解
FileReader MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader
在上面的项目中就是在本地上传图片时用到了 FileReader 将图片转换成 Base64 编码
1 2
   |  FileReader.readAsDataURL()
 
  | 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | 
  $('#file').on("change", function () {   var file = this.files[0]      var fr = new FileReader()   fr.readAsDataURL(file)   fr.onload = function () {     socket.emit("sendImage", {       username: username,       avatar: avatar,              img: fr.result     })   } })
 
  | 
参考:H5 FileReader对象
scrollIntoView
项目中、当我们像每次发完消息时、希望定位到最新的一条、也就是滚动到最底部、我们就需要使用 scrollIntoView
示例:
1 2 3 4
   | function scroll() {      $('.box-bd').childnet(':last').get(0).scrollIntoView(false) }
  | 
参考 scrollIntoView()的用法