vscode通信协议

概述

Vscode渲染进程与插件是运行在不同的进程中的,为了能访问插件的功能,两者之间必须建立通信通道。
Vscode使用的是socket进行进程间的通信,因为是在本地进程间通信,而且TCP/IP协议栈更复杂,为了提高效率,使用了文件协议的socket。Windows上采用命名管道,类unix系统上采用UNIX 域。
由于socket是面向字节流的,需要定义应用层协议,来使双方识别通信报文。

协议介绍

一般通信协议会规定以下两种结构:

  1. 报文的开始与结束标识,如果报文body出现了相同的标识是需要做转义的。
    定义开始与结束标识,主要是为了容错。出现畸形报文后,通过开始与结束标识,后续可以继续识别正常的报文。
  2. 报文结构,即一帧报文各个字节代表的意义,一般报文分为报文头,与报文体。
    报文头定义处理协议时需要的参数,比如报文体的长度,协议版本。以IP协议为例,IP协议的报文头中包含源、宿端地址,因为处理IP报文的时候需要这两个参数,用于报文的转发。
    报文体就是有效数据。如果上面还有协议则为上层协议处理后的数据,如果上层没有协议则直接为程序中发送的数据。
    定义好报文结构后,协议处理程序,就可以将一帧报文的字节数据,转成应用能够识别的数据。

Vscode设计的通信协议,只定义了报文结构,未使用开始与结束标识。
报文开始与结束标识一般出现在比较底层的协议层中,主要是为了容错,防止畸形报文,打乱了后面所有的报文的解析。vscode直接基于socket进行通信,而且是单机内通信,不需要做这种多余的防护。

报文结构

在这里插入图片描述

源码解读

//接受消息
        _socket.on('data', (data: Buffer) => {
            chunks.push(data);
            totalLength += data.length;
            while (totalLength > 0) {
                //检查是否读过头部文件
                if (state.readHead) {
                    //检查是否大于17个字符
                    if (totalLength >= Protocol._headerLen) {
                        const all = Buffer.concat(chunks);
                        //读第一个字节 判断是否是json
                        state.bodyIsJson = all.readInt8(0) === 1;
                        //读取消息体的长度
                        state.bodyLen = all.readInt32BE(1);
                        state.readHead = false;

                        const rest = all.slice(Protocol._headerLen);
                        totalLength = rest.length;
                        chunks = [rest];
                    } else {
                        break;
                    }
                }
                if (!state.readHead) {
                    // expecting body -> read bodyLen-bytes for
                    // the actual message or wait for more data
                    if (totalLength >= state.bodyLen) {
                        const all = Buffer.concat(chunks);
                        let message = all.toString('utf8', 0, state.bodyLen);
                        if (state.bodyIsJson) {
                            message = JSON.parse(message);
                        }
                        this._onMessage.fire(message);

                        const rest = all.slice(state.bodyLen);
                        totalLength = rest.length;
                        chunks = [rest];

                        state.bodyIsJson = false;
                        state.bodyLen = -1;
                        state.readHead = true;
                    } else {
                        break;
                    }
                }
            }
        });
    }

    //发送数据
    public send(message: any): void {
        //构造消息头
        const header = Buffer.alloc(Protocol._headerLen);
        //构造消息体
        if (typeof message !== 'string') {
            message = JSON.stringify(message);
            header.writeInt8(1, 0);
        }

        const data = Buffer.from(message);
        header.writeInt32BE(data.length, 1);
        //发送消息
        this._writeSoon(header, data);
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值