<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>WebSocket on Last Stand</title><link>https://amatsuzero.github.io/LastStand/tags/websocket/</link><description>Recent content in WebSocket on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Tue, 02 Jun 2026 20:30:00 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/tags/websocket/index.xml" rel="self" type="application/rss+xml"/><item><title>WebSocket</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/javascript/websocket/</link><pubDate>Fri, 08 Nov 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/javascript/websocket/</guid><description>&lt;h2 id="一什么是websocket"&gt;一、什么是WebSocket&lt;/h2&gt;
&lt;p&gt;WebSocket 是一种在单个TCP连接上进行全双工通信的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单，允许服务端主动向客户端推送数据。&lt;/p&gt;
&lt;p&gt;在 WebSocket API 中，浏览器和服务器只需要完成一次握手，两者之间就直接可以创建持久性的连接， 并进行双向数据传输。（维基百科）&lt;/p&gt;
&lt;p&gt;WebSocket本质上一种&lt;code&gt;计算机网络应用层的协议&lt;/code&gt;，用来弥补http协议在持久通信能力上的不足。&lt;/p&gt;
&lt;p&gt;WebSocket 协议在2008年诞生，2011年成为国际标准。现在最新版本浏览器都已经支持了。&lt;/p&gt;
&lt;p&gt;它的最大特点就是，服务器可以主动向客户端推送信息，客户端也可以主动向服务器发送信息，是真正的双向平等对话，属于&lt;a href="https://en.wikipedia.org/wiki/Push_technology"&gt;服务器推送技术&lt;/a&gt;的一种。&lt;/p&gt;
&lt;p&gt;WebSocket 的其他特点包括：&lt;/p&gt;
&lt;p&gt;（1）建立在 TCP 协议之上，服务器端的实现比较容易。&lt;/p&gt;
&lt;p&gt;（2）与 HTTP 协议有着良好的兼容性。默认端口也是80和443，并且握手阶段采用 HTTP 协议，因此握手时不容易屏蔽，能通过各种 HTTP 代理服务器。&lt;/p&gt;
&lt;p&gt;（3）数据格式比较轻量，性能开销小，通信高效。&lt;/p&gt;
&lt;p&gt;（4）可以发送文本，也可以发送二进制数据。&lt;/p&gt;
&lt;p&gt;（5）没有同源限制，客户端可以与任意服务器通信。&lt;/p&gt;
&lt;p&gt;（6）协议标识符是&lt;code&gt;ws&lt;/code&gt;（如果加密，则为&lt;code&gt;wss&lt;/code&gt;），服务器网址就是 URL。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ws&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#75715e"&gt;//example.com:80/some/path
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/javascript/websocket/image-01.webp"&gt;&lt;/p&gt;
&lt;h3 id="为什么需要-websocket"&gt;为什么需要 WebSocket？&lt;/h3&gt;
&lt;p&gt;我们已经有了 HTTP 协议，为什么还需要另一个协议？它能带来什么好处？&lt;/p&gt;
&lt;p&gt;因为 HTTP 协议有一个缺陷：通信只能由客户端发起，不具备服务器推送能力。&lt;/p&gt;
&lt;p&gt;举例来说，我们想了解查询今天的实时数据，只能是客户端向服务器发出请求，服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/javascript/websocket/image-02.webp"&gt;&lt;/p&gt;
&lt;p&gt;这种单向请求的特点，注定了如果服务器有连续的状态变化，客户端要获知就非常麻烦。我们只能使用&lt;a href="https://www.pubnub.com/blog/2014-12-01-http-long-polling/"&gt;&amp;ldquo;轮询&amp;rdquo;&lt;/a&gt;：每隔一段时候，就发出一个询问，了解服务器有没有新的信息。最典型的场景就是聊天室。轮询的效率低，非常浪费资源（因为必须不停连接，或者 HTTP 连接始终打开）。&lt;/p&gt;
&lt;p&gt;在 WebSocket 协议出现以前，创建一个和服务端进双通道通信的 web 应用，需要依赖HTTP协议，进行不停的轮询，这会导致一些问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;服务端被迫维持来自每个客户端的大量不同的连接&lt;/li&gt;
&lt;li&gt;大量的轮询请求会造成高开销，比如会带上多余的header，造成了无用的数据传输。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;http协议本身是没有持久通信能力的，但是我们在实际的应用中，是很需要这种能力的，所以，为了解决这些问题，WebSocket协议由此而生，于2011年被IETF定为标准RFC6455，并被RFC7936所补充规范。&lt;/p&gt;
&lt;p&gt;并且在HTML5标准中增加了有关WebSocket协议的相关api，所以只要实现了HTML5标准的客户端，就可以与支持WebSocket协议的服务器进行全双工的持久通信了。&lt;/p&gt;
&lt;h3 id="websocket-与-http-的区别"&gt;WebSocket 与 HTTP 的区别&lt;/h3&gt;
&lt;p&gt;WebSocket 与 HTTP的关系图：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/javascript/websocket/image-03.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;相同点：&lt;/strong&gt; 都是一样基于TCP的，都是可靠性传输协议。都是应用层协议。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;联系：&lt;/strong&gt; WebSocket在建立握手时，数据是通过HTTP传输的。但是建立之后，在真正传输时候是不需要HTTP协议的。&lt;/p&gt;
&lt;p&gt;下面一张图说明了 HTTP 与 WebSocket 的主要区别：&lt;/p&gt;</description></item><item><title>AIRead 实战拆解：KMM 语音播报 SDK 从 start 到双端播放链路</title><link>https://amatsuzero.github.io/LastStand/posts/kmmaireadpractice/</link><pubDate>Tue, 02 Jun 2026 20:30:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/kmmaireadpractice/</guid><description>&lt;h2 id="阅读导航建议先看"&gt;阅读导航（建议先看）&lt;/h2&gt;
&lt;p&gt;如果你是第一次接触这套 SDK，建议按下面顺序读：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先看 2 章&lt;/strong&gt;：理解 commonMain 与双端 actual 的职责边界；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再看 5~6 章&lt;/strong&gt;：把“主流程 + 双端播放器实现”串起来；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最后看 10 章&lt;/strong&gt;：按需查 Debug 手册，不必一次读完。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果你只想快速建立整体认知，优先看 &lt;code&gt;0 + 5 + 9 + 12&lt;/code&gt; 四节即可。&lt;/p&gt;
&lt;h2 id="0-这篇写什么"&gt;0. 这篇写什么&lt;/h2&gt;
&lt;p&gt;这篇不再重复 KMM 概念，而是聚焦一件事：&lt;strong&gt;AIRead 这套 KMM SDK 在工程上到底怎么跑起来&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;会重点回答四个问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;工程目录怎么分层；&lt;/li&gt;
&lt;li&gt;核心 API 给了什么能力；&lt;/li&gt;
&lt;li&gt;从 &lt;code&gt;start(contentId, sentenceId)&lt;/code&gt; 到播放/高亮/回调/重连，链路如何闭环；&lt;/li&gt;
&lt;li&gt;Android（ExoPlayer）和 iOS（AVPlayer）分别承担了什么。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;KMM 基础与平台适配背景放在上一篇：&lt;a href="https://amatsuzero.github.io/LastStand/posts/kmm/"&gt;KMM 基础篇&lt;/a&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-仓库目录总览"&gt;1. 仓库目录总览&lt;/h2&gt;
&lt;p&gt;AIRead 仓库根目录：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AIRead/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── androidApp/ # Android 示例应用（Compose + WebView）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── iosApp/ # iOS 示例应用（SwiftUI + WKWebView）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── shared/ # KMM SDK 主模块
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── gradle/ # 版本目录、发布脚本、wrapper
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── build.gradle.kts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── settings.gradle.kts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── gradle.properties
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── README.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;先按根目录分工看一眼：&lt;/p&gt;</description></item></channel></rss>