websocket

粘包问题的处理

为什么会粘包?

  1. 发送数据的几种可能出现的情况
    image

假设客户端给服务器发送两个数据包:D1、D2,由于服务器一次从接收缓冲区中读取的字节数是不确定的,所以可能存在以下几种情况:
(1)服务器分别收到D1和D2,没有粘包和拆包;
(2)服务器一次收到D1和D2,称为TCP粘包;
(3)服务器分别读取了这两个数据包,第一次读到了D1的完整部分 和 D2的部分数据,第二次读到了D2的剩余部分,称为TCP拆包;
或者服务器第一次读取出D1的部分,第二次读出D1的剩余部分和D2的完整部分;
或者D1和D2都非常大,期间发生多次拆包。

  1. 发生粘包和拆包的原因:
    (1)发送端:应用程序调用write()写入的字节大小大于套接口缓冲区的大小(拆包);
    (2)发送端:进行MSS大小的TCP分片(拆包);
    (3)发送端:基于Nagle算法的小包合并(粘包);
    (4)接收端:应用程序调用read()读取的字节长度过小,可能发生拆包;read()读取过大,可能发生粘包。

  2. 解决方案:
    由于底层协议无法理解上层的业务数据,所以依靠TCP层是无法保证数据不被拆分和重组的,只能通过应用层协议栈的处理来解决

    1. 固定大小
    2. 固定结尾字符(FTP)
    3. 将数据包分为包头包体(http, websocket, 等)
    4. 其他 高级且复杂的应用层协议

图解网络 3.9 既然有 HTTP 协议,为什么还要有 WebSocket?

视频参考资料

需要注意的是,以下所讲的HTTP 在没有特殊强调的情况下都指HTTP 1.1 版本

简单的回答

我们的HTTP 协议的设计初衷是应对看看网页这类简单的场景,所以早期的HTTP 协议是只能由客户端发请求,服务端做出响应(半双工)。

实际应用中有很多需求是在客户端不进行任何操作的情况下,可以对页面进行更新。例如: 网页游戏,网页聊天室,广告、等、

对这种需求依赖不是很重的情况下 我们还可以借助轮训的方式去,假装服务器给我们推消息。但是需求很重的时候,HTTP 就没有办法胜任了。

所以有了websocket

场景演示 (在没有websocket的时候,我们如何实现使用http达到服务器类似的推送效果的)

短轮询(2s 一个接口)

图例:
image

存在问题是什么?

  1. 频繁请求消耗带宽
  2. 极端情况下,用户扫码后最长需要2s (设置的定时时长)才能得到响应,然后再等扫码后的请求响应回来,前端页面才能得到反馈。

更优解 长轮训(30 - 20s)

image

扫码前
image
扫码后(请求参数变化了)
image
手机点击确认登录后,网页刷新页面,立马给页面返回数据渲染新的页面

为什么扫码点击确认后,服务端可以较为及时的响应客户端?![image]

长轮训有什么弊端?
我们为什么不直接http 2.0 推一个消息给客户端?
我们为什么不裸tcp 直接推送消息给客户端?

WebSocket 是什么

半双工: 同一时间里,只能单独一方给对方发送消息 ==> HTTP 1.1
image

全双工: 同一时间里,客户端、服务端均可以向对方发送消息 ==> TCP
image

image

基于TCP的应用层协议

image

WebSocket 与socket 有什么联系?
image

WebSocket 怎么建立连接

首先会进行一次HTTP 请求(请求协议切换);这里的请求会在请求头里面带特殊的参数
image
响应头里面也会有响应的信息(101)
image

image

手撕websocket

// 0 安装node.js 环境
// 1. 使用vs创建项目
// 2. 初始化package.json
npm init -y
// 3. 安装socket 依赖
npm i ws
// 4. 创建server.js
touch server.js
// 5. 使用node 启动服务器
node server.js

总结:

  • TCP 协议本身是全双工的,但我们最常用的 HTTP/1.1,虽然是基于 TCP 的协议,但它是半双工的,对于大部分需要服务器主动推送数据到客户端的场景,都不太友好,因此我们需要使用支持全双工的 WebSocket 协议。

  • 在 HTTP/1.1 里,只要客户端不问,服务端就不答。基于这样的特点,对于登录页面这样的简单场景,可以使用定时轮询或者长轮询的方式实现服务器推送(comet)的效果。

  • 对于客户端和服务端之间需要频繁交互的复杂场景,比如网页游戏,都可以考虑使用 WebSocket 协议。

  • WebSocket 和 socket 几乎没有任何关系,只是叫法相似。

  • 正因为各个浏览器都支持 HTTP协 议,所以 WebSocket 会先利用HTTP协议加上一些特殊的 header 头进行握手升级操作,升级成功后就跟 HTTP 没有任何关系了,之后就用 WebSocket 的数据格式进行收发数据。

posted @ 2023-05-04 01:59  shafujiu  阅读(35)  评论(0)    收藏  举报