学习websocket,原来这么简单

简介: 学习websocket,原来这么简单

简单介绍 websocket

WebSocket是一种在TCP连接上进行全双工通信的协议。
WebSocket通信协议于2011年被IETF定为标准。
然后WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,
允许服务端主动向客户端推送数据。
在WebSocket API中,浏览器和服务器只需要完成一次握手。
两者之间就直接可以创建持久性的连接,并进行双向数据传输。

我们为什么要使用 websocket

我们都知道 HTTP 协议有一个缺陷。
那就是通信只能由客户端发起。服务端没法主动发起。
有些场景我们需要让客户端实时知道消息。
虽然可以使用轮询来解决这个问题。
但是非常浪费资源,因为要不停连接,断开后又继续连接。
这个时候我们就需要使用 websocket

websocket 应用场景

1.弹幕媒体聊天 [客服推送]
2.协同编辑 [wps]
3.基于位置的应用 [外卖]
4.体育实况更新
5.股票帮金报价实时更新

websocket 和HTTP请求的不同点:

1.WebSocket是双向通信协议,HTTP是单向的
WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。而HTTP是单向的
2.连接方式不同
WebSocket是需要浏览器和服务器握手进行建立连接的。
http是浏览器发起向服务器的连接,服务器预先并不知道这个连接。
3.协议开头不同
websocket:websocket的协议是以 ws/wss 开头。
http 对应的是 http/https
4.连接长度不同
websocket是持久连接。http 是短连接。

简单实现一下 WebSocket

node创建WebSocket
我们需要先下载 npm install ws
ws是一个简单易用、快速且经过全面测试的WebSocket客户端和服务器实现。
我们就直接使用就好了
const express = require('express')
const app = express()
const port = 3000
// 托管静态资源-express.static()
app.use(express.static('public'))
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
// 引入 ws,并且解构使用我们需要的 WebSocketServer        
const { WebSocketServer } = require('ws');
// 创建WebSocketServer的实例wss,并指定端口号
const wss = new WebSocketServer({ port: 8080 });
// 通过实例wss进行监听
wss.on('connection', function connection(ws) {
  ws.on('error', console.error);
  // 接收客户端发送过来的消息
  ws.on('message', function message(data) {
    console.log('客户端发送过来的消息', data);
  });
  ws.send('服务端发送的消息');
});
客户端 WebSocket 的创建
我们需要创建 WebSocket 的实例同时指定端口号。
然后通过 onopen  onmessage onerror 来判断ws的状态事件
下面我们就来简单写一下
<body>
    <h1>欢迎 学习WebSocket </h1>
</body>
<script>
// 创建 WebSocket并指定一个地址
let ws = new WebSocket('ws://localhost:8080')
// 是否链接成功
ws.onopen = (() => {
  console.log("链接成功")
})
// 监听服务端发送过来的消息
ws.onmessage = ((messObj) => {
  console.log('发送过来的消息', messObj)
})
// 连接失败
ws.onerror = (() => {
  console.log('连接失败')
})
</script>

客户端发送消息给服务端

我们需要写一个简单的html界面,
获取到 文本域中的内容。
然后通过 ws.send(textareaValue) 给服务端发送消息。
服务端在 
ws.on('message', function message(data) {
  console.log(data)
}) 
这个方法中接收客户端的消息
data就是客户端发送过来的消息
如果是二进制数据,我们可以使用 data.toString()进行转换
<body>
    <h1>欢迎 学习WebSocket </h1>
    <textarea rows="10" cols="30" id="textarea" placeholder="请输入内容"></textarea>
    <button onclick="sendHandler()">点击按钮</button>
</body>
// 创建 WebSocket并指定一个地址
let ws = new WebSocket('ws://localhost:8080')
let textarea=document.getElementById('textarea')
function sendHandler(){
  const textareaValue = textarea.value;
  // 通过ws.send给客户端发送消息
  ws.send(textareaValue)
}

WebSocket 实现广播

我们要做一个广播。
就有点类似在QQ群中发送一条消息,
在这个群中的其他用户可以接收到这条消息。
WebSocket 连接成功后,wss.clients来获取当前服务端连接了多少个客户端。
wss.clients是一个Set类型的。我们通过 forEach 来进行遍历。
我们通过 client.readyState 的状态是否是 WebSocket.OPEN
然后调用 client.send(data, { binary:false  })就数据发送出去
// 引入 ws,并且解构使用我们需要的 WebSocketServer        
const { WebSocketServer, WebSocket } = require('ws');
// import { WebSocketServer } from 'ws';
// 创建WebSocketServer的实例wss,并指定端口号
const wss = new WebSocketServer({ port: 8080 });
// 通过实例wss进行监听
wss.on('connection', function connection(ws) {
  ws.on('error', console.error);
  // 客户端
  ws.on('message', function message(data) {
    console.log('received: %s', data);
    // 服务器广播
    // 广播到所有连接的WebSocket客户端,包括其自身。
    console.log('连接了多少个',wss.clients.size)
    wss.clients.forEach(function each(client) {
      // 判断当前连接服务端的所有客户端的ws。
      if (client.readyState === WebSocket.OPEN) {
        // binary表示数据是否是二进制。binary:false表示不是二进制
        client.send(data, { binary:false  });
      }
    });
  });
  ws.send('服务端发送的消息');
});

发现自己也被广播了

假设不同的浏览器代码一个用户。
通过上面的图片,我们发现谷歌浏览器发送一条消息。
虽然火狐浏览器接收到了。但是谷歌发送的消息自己也接收到了。
这样明显是不正确的。因此。我们处理一下。
自己发送的消息不需要广播自己的。
我们使用 client!==ws 来进行判断
// 引入 ws,并且解构使用我们需要的 WebSocketServer        
const { WebSocketServer, WebSocket } = require('ws');
// import { WebSocketServer } from 'ws';
// 创建WebSocketServer的实例wss,并指定端口号
const wss = new WebSocketServer({ port: 8080 });
// 通过实例wss进行监听
wss.on('connection', function connection(ws) {
  ws.on('error', console.error);
  // 客户端
  ws.on('message', function message(data) {
    console.log('received: %s', data);
    // 服务器广播
    // 广播到所有连接的WebSocket客户端,包括其自身。
    console.log('连接了多少个',wss.clients.size)
    wss.clients.forEach(function each(client) {
      // 判断当前连接服务端的所有客户端的ws用户。
      // client!==ws 表示不是当前发送的用户[不要自己广播自己]
      if (client!==ws && client.readyState === WebSocket.OPEN) {
        // binary表示数据是否是二进制。binary:false表示不是二进制
        client.send(data, { binary:false  });
      }
    });
  });
  // 第一次连接成功后发送的消息。
  ws.send('');
});

实现关闭页面关闭 WebSocket

当我们离开连接 WebSocket的页面离开后,
我们应该关闭当前连接。
可是现在我们点击去user页面的时候,并没有关闭连接。
这显然是不太好的。所以我们需要优化一下。
当用户离开,我们需要关闭连接
// 关闭当前窗口,按下 F5 或点击以下链接触发 onbeforeunload 事件
document.body.onbeforeunload = function () {
  ws.close()
  return 'close'
}
//离开当前页面会触发
window.onunload = function (e) {
  var e = window.event || e;
  console.log('===>',e)
  // 离开页面,关闭WebSocket
  ws.close()
}

携带token

我们在连接 WebSocket 的时候,
没有鉴权,也就是说无法判断当前这个用户的信息。
这样是不安全的。
因此我们在连接 WebSocket 需要携带token.
通过这样的形式携带  ws://localhost:8080?token=' + 'tokne_zahngsan'
// 创建 WebSocket并指定一个地址,并且携带一个token
let ws = new WebSocket('ws://localhost:8080?token=' + 'tokne_zahngsan')
//省略其他代码
wss.on('connection', function connection(ws,req) {
  // 获取前端携带的token
  console.log('req', req.url.slice(8))
})

遇见问题,这是你成长的机会,如果你能够解决,这就是收获。

相关文章
|
8天前
|
移动开发 JavaScript 前端开发
webSocket 学习
vwebSocket 学习
25 0
|
前端开发 Python
Flask学习与实战11:WebSocket的使用与简单通信
用这个协议最方便的就是,服务器主动向客户端推送信息。客户端也可以主动向服务器发送信息。属于应用层协议,在握手阶段还是使用了HTTP的协议。
Flask学习与实战11:WebSocket的使用与简单通信
|
移动开发 网络协议 安全
Swoole 学习之基于 Websocket 弹幕的实现
Swoole 学习之基于 Websocket 弹幕的实现
235 0
Swoole 学习之基于 Websocket 弹幕的实现
|
Web App开发 移动开发 JavaScript
python websocket学习使用
前言 今天看了一些资料,记录一下心得。 websocket是html5引入的一个新特性,传统的web应用是通过http协议来提供支持,如果要实时同步传输数据,需要轮询,效率低下 websocket是类似socket通信,web端连接服务器后,握手成功,一直保持连接,可以理解为长连接,这时服务器就可以主动给客户端发送数据,实现数据的自动更新。
3847 0
|
缓存 网络协议 安全
RSocket 学习(二):HTTP VS WebSocket VS RSocket
RSocket 学习(二):HTTP VS WebSocket VS RSocket
369 0
RSocket 学习(二):HTTP VS WebSocket VS RSocket
|
JavaScript 网络协议 Java
WebSocket学习
WebSocket学习 为什么需要WebSocket 以往使用的HTTP协议存在一个缺陷,通信只能由客户端发起。 这种单向请求的特点,如果有一个添加好友的业务场景存在,那就注定客户端必须采用轮询的机制,去设置间隔时间,不断地去请求服务端,无疑对客户端存在延时操作,同时也是对服务端的一种极大的损耗。
1832 0
|
Web App开发 应用服务中间件 nginx
|
Web App开发 前端开发 网络协议
Websocket协议的学习、调研和实现
1. websocket是什么 Websocket是html5提出的一个协议规范,参考rfc6455。 websocket约定了一个通信的规范,通过一个握手的机制,客户端(浏览器)和服务器(webserver)之间能建立一个类似tcp的连接,从而方便c-s之间的通信。
1918 0
|
网络协议 前端开发 安全
websocket和http的瓜葛以及websocket协议实现
websocket和http的瓜葛以及websocket协议实现
websocket和http的瓜葛以及websocket协议实现
|
JavaScript
js实现websocket实例
js实现websocket实例
201 0