https://www.yuque.com/cjc1216/mgm0hh/smlszn

背景

长轮询: 客户端每隔很短时间,都会对服务器发送请求,采用阻塞模型查看是否有新的消息,只要轮询速度足够快,就会有一种交互上的实时的错觉。实际上对服务端、客户端都造成很大的浪费
长链接:客户端只请求一次,但是服务器将会保持持久链接,不会返回结果,当服务器有了新数据,才返回结果,一直保持挂起状态,对服务端造成很大的浪费

  • 服务端被迫维持来自每个客户端的大量不同的连接
  • 大量的轮询请求会造成高开销,比如会带上多余的header,造成了无用的数据传输

WebSocket是HTML5开始提供一种在单个TCP连接上进行全双工通信的协议 ,来弥补HTTP协议在持久通信能力上的不足,允许服务端主动向客户端推送数据,2011年成为国际标准

在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接, 并进行双向数据传输
image.png
推荐文档:https://tools.ietf.org/html/rfc6455

socket套接字

百度百科:https://baike.baidu.com/item/%E5%A5%97%E6%8E%A5%E5%AD%97/9637606?fromtitle=socket&fromid=281150&fr=aladdin

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个 socket(套接字),上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口

特点

  • 通信的基石,是支持TCP/IP协议的路通信的基本操作单元
  • 建立网络通信连接至少要一对端口号,一个运行于客户端,为 Client Socket。一个运行于服务器端,为Server Socket
  • socket并不是协议,本质是对 TCP/IP 协议栈的封装,它提供了一个针对 TCP 或者 UDP 编程的接口,并不是另一种协议

    客户端API

    WebSocket.readyState

  • 0: 表示正在连接

  • 1: 表示连接成功,可以通信了
  • 2: 表示连接正在关闭
  • 3: 表示连接已经关闭,或者打开连接失败
  1. const ws = new WebSocket("ws//:xxx.xx", [protocol])
  2. ws.onopen = () => {
  3. ws.send('hello')
  4. console.log('send')
  5. }
  6. ws.onmessage = (ev) =>{
  7. console.log(ev.data)
  8. ws.close()
  9. }
  10. ws.onclose = (ev) =>{
  11. console.log('close')
  12. }
  13. ws.onerror = (ev) =>{
  14. console.log('error')
  15. }
  16. ws.send()
  17. ws.close()

WebSockets的心跳(兵乓球)

  • 客户端—》服务端:ping
  • 服务端—》客户端:pong

ping、pong 只是一个控制帧

webSocket与http

区别

webSocket http
数据流向 双向通信 单向数据流
协议开头 ws:// || wss:// http:// || https://
同源限制 无同源限制,可跨域 有同源限制
传输开销 数据格式轻量、数据包头部较小 头较大

相同点

  • 都需要建立TCP连接
  • 都属于七层协议中的应用层协议

    缺点

  • 前后端维持住ws连接,否则无法推送接收消息,长连接需要业务代码更稳定

    协议内容

    ```javascript GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com

  1. **Connection** 决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成。**为****Upgrade,意思是****请求升级**<br />**Upgrade**:表示协议升级为webSocket协议<br />**Sec-WebSocket-Extensions:** WebSocket的扩展<br />**Sec-WebSocket-Key:** client 发送的一个 base64 编码的密文,要求 server 必须返回一个对应加密的 "Sec-WebSocket-Accept" 应答,否则 client 会抛出 "Error during WebSocket handshake" 错误,并关闭连接<br />**Sec-WebSocket-Version:** 版本号
  2. 响应头<br />**Sec-WebSocket-Accept:**服务端先获得请求头部的Sec-WebSocket-Key值,然后再其后面连接一个GUID258EAFA5-E914-47DA-95CA-C5AB0DC85B11),对连接后的字符串做SHA1,得到16进制表示的字符串,将每两位当作一个字节进行分隔,得到字节数组,对字节数组做Base64,即得到Sec-WebSocket-Accept的值
  3. <a name="izlV5"></a>
  4. # socket.io 库
  5. Socket.io不是Websocket而是一个封装了 Websocket、基于 Node JavaScript 框架,它只是将Websocket和轮询 Polling)机制以及其它的实时通信方式封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。也就是说,Websocket仅仅是 Socket.io实现实时通信的一个子集,**屏蔽了所有底层细节,让顶层调用非常简单**
  6. <a name="mRVCS"></a>
  7. ## 特点
  8. - 易用性
  9. - 跨平台
  10. - 自适应
  11. <br />
  12. <a name="yW69r"></a>
  13. ## 应用场景
  14. - 实时的聊天
  15. - 数据实时分析,数据传输
  16. - 文件协同合作<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/271643/1597305736647-ac8195f8-673d-4ba1-ad22-2a1ef2b09c77.png#align=left&display=inline&height=305&margin=%5Bobject%20Object%5D&name=image.png&originHeight=610&originWidth=1138&size=657999&status=done&style=none&width=569)
  17. 数据掩码的作用是增强协议的安全性
  18. <a name="DLHww"></a>
  19. ## 客户端
  20. 地址:[https://socket.io/docs/client-api/](https://socket.io/docs/client-api/)<br />socket.io-client 源码分析博客:[https://blog.csdn.net/weixin_41855143/article/details/103334904?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-4-103334904.nonecase](https://blog.csdn.net/weixin_41855143/article/details/103334904?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-4-103334904.nonecase)<br />[https://github.com/MetinSeylan/Vue-Socket.io](https://github.com/MetinSeylan/Vue-Socket.io)
  21. 默认情况下,首先建立长轮询连接,然后将其升级为“更好的”传输(例如WebSocket),如下配置<br />iourl, { transports:[ 'websocket' ] })
  22. <a name="psMHs"></a>
  23. ### API
  24. - iourl)创建一个链接
  25. - socket.on() 监听事件
  26. - socket.emit() 触发事件
  27. - socket.open() 手动打开连接
  28. - socket.close() 手动断开连接
  29. ```javascript
  30. // vue中使用 socket.io-client
  31. import io from 'socket.io-client';
  32. export default {
  33. data () {
  34. return {
  35. socket: io('10.0.25.29:3001')}
  36. },
  37. mounted () {
  38. this.socket.on('MESSAGE', (data) => {
  39. this.messages = [...this.messages, data];
  40. });
  41. },
  42. methods: {
  43. // 发送消息
  44. sendMessage () {
  45. this.socket.emit('SEND_MESSAGE', {
  46. user: this.user,
  47. message: this.message
  48. })
  49. },
  50. // 关闭连接
  51. handleClose () {
  52. // 服务器端关闭
  53. // this.socket.emit('CLOSE')
  54. // 客户端关闭
  55. this.socket.close()
  56. },
  57. // 重新连接
  58. handleAttemp () {
  59. console.log('尝试')
  60. this.socket.open()
  61. }
  62. }
  63. }

Request

image.png

服务端

地址:https://socket.io/docs/server-api/

API

  • io.on() 监听事件 connection 监听连接、 disconnect 监听断开
  • io.emit() 触发事件
  • io.close() 关闭事件
  • io.of(nsp) 初始化并获取Namespace其路径名标识的给定nsp,NameSpace 命名空间,隔离作用域,或者划分业务模块,推荐使用
  • socket.broadcast.emit() 该事件发出将仅向除发送方以外的所有套接字广播事件数据
  • socket.id 会话的唯一标识符(可以进行私聊) join leave to() ```javascript const express = require(‘express’); const app = express();

const server = app.listen(3001, ‘10.0.25.29’, function () { console.log(‘server running on port 3001’); });

const io = require(‘socket.io’)(server);

io.on(‘connection’, function (socket) { console.log(“用户” + socket.id + “连接”) socket.on(‘SEND_MESSAGE’, function (data) { socket.emit(‘MESSAGE’, data) }); // 关闭服务器 socket.on(‘CLOSE’, function () { socket.close() }) // 监听断开事件 socket.on(‘disconnect’, function () { console.log(“用户” + socket.id + “断开连接”) }) }); ```

Response

image.png

  • pingInterval 发送新的ping数据包之前多少毫秒
  • pingTimeout 没有pong数据包需要多少毫秒才能考虑连接已关闭
  • sid 本次 EIO Socket 的会话 ID
  • 绿色是发送,白色是接收,左侧前面数字是数据包类型,ping—>2, pong—>3, message—>4

介绍stomp

stomp+socket 开发过酒店管理系统的前台推送消息部分
地址:http://jmesnil.net/stomp-websocket/doc/
一个简单的面向文本/流的消息协议
Stomp.over(ws)方法来使用其他类型的WebSocket

流程图

wireShark

Frame: 物理层的数据帧概况
Ethernet II: 数据链路层以太网帧头部信息
Internet Protocol Version 4: 互联网层IP包头部信息
Transmission Control Protocol: 传输层T的数据段头部信息,此处是TCP
Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议
Line-based text data: 是服务器所响应而返回的页面内容

tcp retransmission原因
TCP协议是一个可靠的协议。它通过重新发送(retransmission)来实现TCP片段传输的可靠性。简单的说,TCP会不断重复发送TCP片段,直到片段被正确接收

进程突然杀死、持续刷新生成几个socket