我正在使用websockets将视频图像从用Go编写的服务器传输到HTML页面的客户端。我在下面分享的经验是使用Chrome的。
我通过 websocket 的消息处理程序接收图像。在接收图像时,我可能需要异步完成许多任务,然后才能显示图像。即使这些任务没有完成,另一个 onmessage() 也可能会触发。我不想对图像进行排队,因为此时我无法像服务器继续那样快速进行,并且因为显示旧图像没有意义。我也不想丢弃这些图像,我根本不想接收它们。
如果客户端使用传统的TCP连接,它只会停止从连接读取。这将导致接收缓冲区被填满,接收窗口关闭,并最终暂停在服务器上发送图像。一旦客户端开始读取,接收缓冲区将清空,接收窗口将打开,服务器将恢复传输。每次我的服务器开始发送图像时,它都会选择最新的图像。这种选择最新鲜的行为,加上TCP的流量控制,在许多情况下确保了合理的行为。
是否有可能具有 websocket 所基于的 TCP 的流量控制功能?我对依赖于TCP的流量控制而不依赖于应用程序级流量控制的解决方案特别感兴趣,因为这往往会产生不必要的额外延迟。
在 WebSocket 中使用流。Chrome 78将附带一个新的WebSocketStream API,它支持背压。
以下是来自Chrome平台状态的引述:
WebSocket API 为RFC6455提供了一个 JavaScript 接口 WebSocket 协议。虽然它服务得很好,但从 人体工程学角度和缺少的重要特征 背压。WebSocketStream API 的目的是解决 通过将流与 WebSocket API 集成来解决这些缺陷。
当前无法对收到的消息应用背压 使用 WebSocket API。当消息到达的速度超过页面时 处理它们,渲染过程要么填满内存缓冲 这些消息由于 100% CPU 使用率而变得无响应,或两者兼而有之。
对发送的消息应用背压是可能的,但涉及 轮询低效的 bufferedAmount 属性,并且 不符合人体工程学。
不幸的是,这是一个仅限Chrome的API,没有网络标准在撰写本文时。
有关详细信息,请参阅:
- 问题 983030:实施 WebSocketStream
我怀疑你所要求的是可能的。 WebSocket API 规范中没有该功能的接口。 但是,规范所概述的是要求在使用 WebSocket 的脚本之外的后台管理基础套接字连接,以便脚本不会被 WebSocket 操作阻止。 当套接字接收入站数据时,它会将数据包装在消息中,并将其排队等待 WebSocket 脚本处理。 没有什么可以阻止套接字读取更多数据,而消息仍保留在队列中等待脚本处理它们。
唯一可以在 WebSocket 中实现的真正流控制是显式的。 当消息到达时,发回一条消息以确认它。 让服务器等待接收该确认,然后再发送下一条消息。
您可以在 WebSocket 连接上执行流控制(基于 TCP 背压自适应)。以下是帮助您入门的两个链接:
- 使用生产者/消费者模式进行流量控制
- 基于 WebSocket 的分段音频
披露:我是Autobahn的原作者,为Tavendo工作。