进程间通信数据包创建

时间:2015-10-14 12:40:07

标签: java c# .net ipc

我正在编写一个进程间通信协议,其中c#客户端在服务器进程中调用API,这些API将以不同语言(Java,C,C ++等)编写。 这两个进程都在同一台机器上运行,而通信层本身不是问题(目前我正在使用套接字,因为大多数语言都支持它,但以后可能会使用共享内存) 总共有大约180个API,每个API当然都有各自类型的参数集。由于服务器可以用任何语言编写,我将所有参数转换为字节数组,将其放入带有API标识符的数据包中,然后将其发送到另一个进程,根据API标识符对其进行解码。来自服务器进程的返回数据将以相同的方式格式化。

我正在寻找的是最快的方式(最好是单个函数),它采用可变数量的不同类型参数并将它们转换为字节数组。目前,我正在使用BitConverter类将每个参数转换为字节数组,并将所有数组连接成一个。除了字符串之外没有引用类型参数,它们将转换为包含字符串长度的前2个字节的字节数组。我可以控制客户端和服务器,因此每个人都知道数据包中预期的参数顺序(基于API ID)和每个参数的大小。

如果有另一种方法可以使用以下单一功能来执行此操作或如何执行此操作:

byte[] toByteArray (variable-number of different-type parameters…)

请告诉我。性能是一个问题,因为API调用的频率非常高。

2 个答案:

答案 0 :(得分:0)

我认为您应该尝试使用Google的协议缓冲区:https://developers.google.com/protocol-buffers/

Protobuf与语言无关。因此,您定义自己的结构,然后为Java,C#,C ++等生成特定的代码。

答案 1 :(得分:0)

我选择使用以下代码。最初担心使用params和装箱/拆箱的性能损失,但经过一些分析后,它可以忽略不计。这是适合任何有兴趣的人。

    public static int ToByteArray (byte[] bytes, int Offs, params object[] args)
    {
        int CurrIdx = Offs;

        for (int i=0; i<args.Length; i++)
        {
            object obj = args[i];
            if (obj is int)
            {
                int x = (int) obj;
                bytes[CurrIdx++] = (byte)(x & 0xff);
                bytes[CurrIdx++] = (byte)((x >> 8) & 0xff);
                bytes[CurrIdx++] = (byte)((x >> 16) & 0xff);
                bytes[CurrIdx++] = (byte)((x >> 24) & 0xff);
            }
            else if (obj is double)
            {
                double x = (double)obj;
                System.Buffer.BlockCopy(BitConverter.GetBytes(x), 0, bytes, CurrIdx, sizeof(double));
                CurrIdx += sizeof(double);
            }
            else if (obj is string)
            {
                string x = (string)obj;
                int ByteLen = x.Length * sizeof(char);
                bytes[CurrIdx++] = (byte)(x.Length & 0xff);
                bytes[CurrIdx++] = (byte)((x.Length >> 8) & 0xff);
                System.Buffer.BlockCopy(x.ToCharArray(), 0, bytes, CurrIdx, ByteLen);
                CurrIdx += ByteLen;
            }
        }
        return (CurrIdx - Offs);
    }