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

多窗口/实例下Chrome Native Messaging的数据同步问题

Chrome原生宿主多实例同步与数据完整性解决方案

1. 先解决单消息的完整读取问题

Chrome原生消息的通信协议是4字节小端无符号整数(消息长度) + UTF-8编码的JSON payload,必须严格按照这个格式读取,才能避免消息截断或混读。直接读行/字节流的方式会导致多请求内容混杂,核心逻辑是先读长度,再读对应长度的内容。

C#读取完整消息的示例代码:

private static string ReadMessage()
{
    try
    {
        var stdin = Console.OpenStandardInput();
        // 读取4字节长度(小端)
        byte[] lengthBytes = new byte[4];
        int bytesRead = stdin.Read(lengthBytes, 0, 4);
        if (bytesRead != 4) return null;

        int messageLength = BitConverter.ToInt32(lengthBytes, 0);
        if (messageLength <= 0) return null;

        // 循环读取确保读满指定长度的消息内容
        byte[] messageBytes = new byte[messageLength];
        bytesRead = 0;
        while (bytesRead < messageLength)
        {
            int read = stdin.Read(messageBytes, bytesRead, messageLength - bytesRead);
            if (read == 0) return null;
            bytesRead += read;
        }

        return Encoding.UTF8.GetString(messageBytes);
    }
    catch (Exception)
    {
        return null;
    }
}

2. 原生端共享状态的同步保护

同扩展ID下,Chrome会复用同一个原生宿主进程,多窗口/扩展实例的请求都会发到该进程,你需要在原生端用锁机制保护共享状态:

2.1 锁的选择

  • 读多写少场景:用ReaderWriterLockSlim,允许多个读请求同时执行,写请求独占资源,提升并发效率。
  • 读写频率相当或写操作频繁:用Mutex或lock关键字,保证所有操作串行执行。

2.2 示例实现(读写锁)

// 共享状态
private static string _sharedData = "初始数据";
// 读写锁实例
private static readonly ReaderWriterLockSlim _dataLock = new ReaderWriterLockSlim();

private static string ProcessRequest(string request)
{
    // 实际项目建议用JSON库(如System.Text.Json)解析请求
    if (request.Contains("\"action\":\"read\""))
    {
        // 读操作加读锁
        _dataLock.EnterReadLock();
        try
        {
            return $"{{\"status\":\"ok\",\"data\":\"{_sharedData}\"}}";
        }
        finally
        {
            _dataLock.ExitReadLock();
        }
    }
    else if (request.Contains("\"action\":\"write\""))
    {
        // 模拟从请求中提取新数据
        string newData = "更新后的共享数据";
        // 写操作加写锁
        _dataLock.EnterWriteLock();
        try
        {
            _sharedData = newData;
            return "{\"status\":\"ok\"}";
        }
        finally
        {
            _dataLock.ExitWriteLock();
        }
    }
    return "{\"status\":\"error\",\"msg\":\"未知操作\"}";
}

3. 响应发送的规范

发送响应时同样要遵循协议:先写4字节长度,再写JSON内容,确保Chrome能正确解析并路由到对应的扩展实例:

private static void SendMessage(string message)
{
    try
    {
        var stdout = Console.OpenStandardOutput();
        byte[] messageBytes = Encoding.UTF8.GetBytes(message);
        // 写入4字节小端长度
        byte[] lengthBytes = BitConverter.GetBytes(messageBytes.Length);
        stdout.Write(lengthBytes, 0, 4);
        // 写入消息内容
        stdout.Write(messageBytes, 0, messageBytes.Length);
        stdout.Flush();
    }
    catch (Exception)
    {
        // 处理发送异常
    }
}

4. 额外注意事项

  • 原生宿主要保持长期运行:不能处理完一个请求就退出,否则Chrome会重新启动宿主,导致共享状态丢失,主逻辑要放在无限循环中。
  • 避免死锁:所有锁的获取必须在finally块中释放,确保异常场景下锁能正常释放。
  • 高并发优化:如果请求量较大,可使用ConcurrentQueue实现生产者-消费者模型,将消息读取和处理解耦,避免stdin读取被阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:14:55