调试分析 BiliBili 直播 WebSocket 协议

本文主要讲如何使用 Chrome DevTools,Bilibili 的直播间 WebSocket 协议只是作为一个案例,互联网上有很多现成的博客已经讲了协议内容。

准备工具#

最新版的 Chrome 浏览器

我的当前版本是 Chrome 70

定位代码#

  1. 打开直播间,打开 F12 开发者工具,刷新页面。

  2. 切换到 Network 选项卡。

  3. 打开筛选,筛选类型为 WS(即 WebSocket)的请求。

Network 选项卡,筛选 WS

  1. 鼠标悬停在代码位置的上方,可以看到请求的发出位置,以及它的调用栈。

    通常类不会是最内层(也就是第一个),往下找几个,估计一个大概的位置。

    如果估计不好的话,最麻烦的方法也就是一个一个看了。

请求调用堆栈

这种顺序逻辑的代码一般都是同步执行的,通常不会越过 (async)。这工作量瞬间就减小到只剩 10 行了。

一般特别要注意 (anonymous) 前后,可能就是跨类调用的部分。这一条的准确性不好,用处通常不大。

如果嫌麻烦的话,可以用稍微高级的方法,继续看下一部分。

下断点反查调用栈#

刚才那个太麻烦了,要用点简单的方法。

我们直接点进第一条,也就是请求真正触发的位置。

调用栈的最顶层就是整个调用的最内层、最深的位置。

点击左下角的 {},格式化一下代码。

然后在这行下一个断点。

刷新页面。

当这个断点断下时,右侧有当前的调用栈,也能看到当前层中的局部变量。可以点击某一层,将代码切换到这一层的调用位置,同时把上下文切换到对应的位置,可以看到对应层的局部变量。左侧的代码中也会内联显示对应行内有关的变量的信息,方便调试。

调用堆栈调试

这个在 Source 选项卡中的栈和之前在 Network 选项卡中的栈是一样的,我们只需要依次往下找,看看哪两层栈之间的上下文变化过于剧烈,就可以找到这个模块大概的层次了。

因为这个 js 文件是通过 webpack 编译出来的,所以才会有模块这种东西。某些其他的 JavaScript 的前端软件,原本就是可以直接用在浏览器,模块也都写在全局变量中的,情况可能会有些不一样。

找到具体位置#

因为代码的大致位置都找到了,在附近找一找 sendonmessageon('message', ...) 就行了。就是通过 Ctrl + F 查找。

可以通过下断点逆推堆栈了解程序执行过程,也可以直接分析代码。

js 代码经过 Uglify 之后,变量名会变成英文字母表,但通常 uglify 只是单纯地替换变量名,不会把不同的变量名替换成相同的变量名,所以静态分析还是可以分析明白的。

分析算法#

这个部分其实没什么,就可以就是单步运行就好了。