You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForms嵌入浏览器中拦截WebSocket数据的实现方法

拦截内嵌浏览器WebSocket推送数据的方案

一、用WebView2控件(推荐,基于Edge Chromium)

WebView2的扩展能力更强,拦截WebSocket数据主要有两种实用方法:

1. 注入JavaScript拦截消息

核心思路是在页面加载时注入脚本,重写WebSocket的onmessage方法,把收到的数据转发给WinForms程序,同时不影响页面原有逻辑。

代码示例:

private async void WebView21_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
    if (e.IsSuccess)
    {
        // 注入拦截WebSocket的JS脚本
        string injectScript = @"
            const OriginalWebSocket = window.WebSocket;
            window.WebSocket = function(url, protocols) {
                const ws = new OriginalWebSocket(url, protocols);
                // 保存原始的onmessage方法
                const originalOnMessage = ws.onmessage;
                ws.onmessage = function(event) {
                    // 把数据发回WinForms
                    window.chrome.webview.postMessage({
                        type: 'ws-data',
                        content: event.data,
                        wsUrl: ws.url
                    });
                    // 调用原始方法,保证页面正常运行
                    if (originalOnMessage) originalOnMessage.call(this, event);
                };
                return ws;
            };
        ";
        await webView21.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(injectScript);

        // 监听WebView2发来的消息
        webView21.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;
    }
}

private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
    // 解析JSON格式的消息
    var message = System.Text.Json.JsonSerializer.Deserialize<WsMessage>(e.WebMessageAsJson);
    if (message.Type == "ws-data")
    {
        // 在这里处理数据
        HandleWsData(message.Content);
    }
}

// 辅助类用于解析消息
public class WsMessage
{
    public string Type { get; set; }
    public string Content { get; set; }
    public string WsUrl { get; set; }
}

private void HandleWsData(string data)
{
    // 你的计算处理逻辑,比如解析、运算
    Console.WriteLine($"拿到WebSocket数据:{data}");
}

2. 网络请求拦截(进阶)

如果需要更底层的控制,可以通过CoreWebView2.AddWebResourceRequestedFilter拦截WebSocket的握手请求,再监听后续的传输帧,但这种方法复杂度高,一般场景用第一种就够了。


二、用WebBrowser控件(IE内核)

WebBrowser基于旧版IE,拦截方式类似但需要借助COM互操作:

  1. 给Form类加上[ComVisible(true)]特性,让JS能调用WinForms方法
  2. 在页面加载完成后注入JS,重写WebSocket的onmessage,把数据传给WinForms

代码示例:

[ComVisible(true)]
public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        // 允许JS调用WinForms对象
        webBrowser1.ObjectForScripting = this;
    }

    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        if (webBrowser1.Document != null)
        {
            string injectScript = @"
                var OriginalWebSocket = window.WebSocket;
                window.WebSocket = function(url, protocols) {
                    var ws = new OriginalWebSocket(url, protocols);
                    var originalOnMessage = ws.onmessage;
                    ws.onmessage = function(event) {
                        // 调用WinForms的方法传数据
                        window.external.GetWsData(event.data, ws.url);
                        if (originalOnMessage) originalOnMessage.call(this, event);
                    };
                    return ws;
                };
            ";
            webBrowser1.Document.InvokeScript("eval", new object[] { injectScript });
        }
    }

    // 供JS调用的公开方法
    public void GetWsData(string data, string url)
    {
        HandleWsData(data);
    }

    private void HandleWsData(string data)
    {
        // 数据处理逻辑
        Console.WriteLine($"收到WebSocket数据:{data}");
    }
}

关于自行创建WebSocket连接的问题

如果服务器支持多连接,用C#的ClientWebSocket直接连是可行的,但要注意:

  • 服务器可能限制单IP连接数,或者需要页面WebSocket的会话信息(比如Cookie、Token),自行连接可能会失败
  • 优先用上面的拦截方法,因为它复用了浏览器已建立的连接,不需要额外处理验证、会话等问题,更稳定

如果要测试自行连接,可以用这段代码:

private async Task TestWsConnection(string targetIp)
{
    using (var ws = new ClientWebSocket())
    {
        try
        {
            // 替换成实际的WebSocket路径,比如ws://xxx/ws
            Uri wsUri = new Uri($"ws://{targetIp}/your-ws-path");
            await ws.ConnectAsync(wsUri, CancellationToken.None);
            Console.WriteLine("连接成功");

            // 循环接收数据
            byte[] buffer = new byte[4096];
            while (ws.State == WebSocketState.Open)
            {
                var result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                if (result.MessageType == WebSocketMessageType.Text)
                {
                    string data = Encoding.UTF8.GetString(buffer, 0, result.Count);
                    HandleWsData(data);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"连接失败:{ex.Message}");
            // 大概率是服务器不支持多连接或者需要验证
        }
    }
}

内容的提问来源于stack exchange,提问作者Leon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 22:20:29