WebSocket调试工具:Fiddler使用指南

WebSocket是一种在单个TCP连接上进行全双工通信的协议。它允许服务器主动向客户端发送消息,是实现实时通信的关键技术。然而,当WebSocket流量很大或每个数据帧很大时,使用浏览器的开发者工具或Fiddler等工具进行调试可能会变得非常困难。本文将介绍如何使用Fiddler(以及FiddlerScript)来检查WebSocket流量,就像检查HTTP流量一样。

Chrome的网络流量检查器显示WebSocket流量在"网络"标签页下的"connect"数据包(101 Switching Protocols)-> "帧"标签页中。WebSocket流量不会自动刷新,除非再次点击101数据包。它不支持"Continuation Frame",如下所示:

Fiddler的日志标签页也有限制:Fiddler日志标签页中的WebSocket流量帧没有分组,因此很难在帧之间导航。继续帧没有被解码,它们显示为二进制。此外,如果有很高的流量,Fiddler会使用100%的CPU并挂起。

解决方案

通过这个解决方案,将获得以下好处:

  • 可以在Fiddler主窗口中看到所有的WebSocket帧,并且可以轻松地在帧之间导航。
  • 可以在"检查器"标签页 -> "请求信息" -> "JSON"子标签页中看到帧的详细信息。
  • 继续帧会自动解码并组合在一起。
  • 所有帧都会自动捕获并显示在Fiddler主窗口中,无需手动刷新。
  • 即使在高流量情况下,Fiddler的CPU使用率也会保持低。

如何工作?

1. 下载Fiddler Web Debugger (v4.4.5.9)

2. 打开Fiddler-> Rules -> Customize Rules... -> 这将打开FiddlerScript

3. 添加以下代码到FiddlerScript:

import System.Threading; class Handlers { static System.Threading.Timer printSocketTimer = null; static System.Collections.Queue socketMessages = new System.Collections.Queue(); static System.Text.StringBuilder requestBodyBuilder = new System.Text.StringBuilder(); static System.Text.StringBuilder requestUrlBuilder = new System.Text.StringBuilder(); static bool requestPayloadIsJson = false; static int requestPartCount = 0; static function Main() { printSocketTimer = new System.Threading.Timer(PrintSocketMessage, null, 0, 2000); } static function OnWebSocketMessage(oMsg: WebSocketMessage) { Monitor.Enter(socketMessages); socketMessages.Enqueue(oMsg); Monitor.Exit(socketMessages); } static function PrintSocketMessage(stateInfo: Object) { Monitor.Enter(socketMessages); while (socketMessages.Count > 0) { var oMsg = socketMessages.Dequeue(); ExtractSocketMessage(oMsg); } Monitor.Exit(socketMessages); } static function ExtractSocketMessage(oMsg: WebSocketMessage) { // ... } static function SendRequest(urlPath: String, message: String) { var request = String.Format( "POST http://fakewebsocket/{0} HTTP/1.1\n" + "User-Agent: Fiddler\n" + "Content-Type: application/json; charset=utf-8\n" + "Host: fakewebsocket\n" + "Content-Length: {1}\n\n{2}", urlPath, message.Length, message); FiddlerApplication.oProxy.SendRequest(request, null); } static function GetWsSession(oMsg: WebSocketMessage) { // ... } static function HexToString(sourceHex: String) { // ... } }

4. 设置Fiddler -> AutoResponder (可选)

已经在Firefox 25.0, IE 11.0, Chrome 32.0.中测试了这个解决方案。这个解决方案应该适用于所有支持WebSocket的浏览器,只要网络代理设置正确。以IE为例:

  • 打开Fiddler,这将自动设置网络代理,但这还不够。
  • 打开IE ->工具-> 互联网选项 -> 连接标签页 -> 点击"LAN设置"按钮
  • 点击"高级"按钮
  • 勾选"对所有协议使用相同的代理服务器"复选框。

测试点

可以通过访问以下网站来测试上述解决方案:

  • http://www.websocket.org/echo.html
  • http://socket.io/demos/chat/
  • https://jabbr.net/ (需要登录。这个网站使用SignalR构建,支持WebSocket)。

上述代码每2秒打印一次WebSocket帧,以避免高CPU使用率,这意味着"统计"标签页中的的时间戳可能会延迟最多2秒。可以根据流量量调整这个计时器。

然而,可以看到帧接收的实际时间,在"检查器"标签页 -> "请求信息" -> "JSON"子标签页 -> doneTime中。

为了简单起见,只为所有WebSocket会话创建了一个队列,继续帧会组合在一起,不管它们的会话ID。请随意扩展代码。现在,一次只调试一个WebSocket会话。

上述代码假设以'{'开头的有效载荷是JSON数据,这对很有用。如果这个假设在情况中是错误的,可以很容易地修改代码。

注意:Socket.IO目前会在有效载荷前加上一个有特殊含义的数字,这使得帧成为无效的JSON数据,即,不能在JSON子标签页中看到漂亮的格式化帧。然而,仍然可以在原始子标签页中看到帧。或者,可以更新脚本来处理Socket.IO的数字前缀。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485