WebSocket是一种在单个TCP连接上进行全双工通信的协议。它允许服务器主动向客户端发送消息,是实现实时通信的关键技术。然而,当WebSocket流量很大或每个数据帧很大时,使用浏览器的开发者工具或Fiddler等工具进行调试可能会变得非常困难。本文将介绍如何使用Fiddler(以及FiddlerScript)来检查WebSocket流量,就像检查HTTP流量一样。
Chrome的网络流量检查器显示WebSocket流量在"网络"标签页下的"connect"数据包(101 Switching Protocols)-> "帧"标签页中。WebSocket流量不会自动刷新,除非再次点击101数据包。它不支持"Continuation Frame",如下所示:
Fiddler的日志标签页也有限制:Fiddler日志标签页中的WebSocket流量帧没有分组,因此很难在帧之间导航。继续帧没有被解码,它们显示为二进制。此外,如果有很高的流量,Fiddler会使用100%的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为例:
可以通过访问以下网站来测试上述解决方案:
上述代码每2秒打印一次WebSocket帧,以避免高CPU使用率,这意味着"统计"标签页中的的时间戳可能会延迟最多2秒。可以根据流量量调整这个计时器。
然而,可以看到帧接收的实际时间,在"检查器"标签页 -> "请求信息" -> "JSON"子标签页 -> doneTime中。
为了简单起见,只为所有WebSocket会话创建了一个队列,继续帧会组合在一起,不管它们的会话ID。请随意扩展代码。现在,一次只调试一个WebSocket会话。
上述代码假设以'{'开头的有效载荷是JSON数据,这对很有用。如果这个假设在情况中是错误的,可以很容易地修改代码。
注意:Socket.IO目前会在有效载荷前加上一个有特殊含义的数字,这使得帧成为无效的JSON数据,即,不能在JSON子标签页中看到漂亮的格式化帧。然而,仍然可以在原始子标签页中看到帧。或者,可以更新脚本来处理Socket.IO的数字前缀。