C# 中的多部分消息流处理

multipart message stream handling in C#

我需要解析包含 protocol-defined binary-formatted 消息的 TCP 数据流,这些消息可能是也可能不是多部分。消息中的 Headers 表示消息是否包含多个部分(第 1 部分,共 4 部分,等等)。我正在使用一条消息 class 成功解析 single-part 消息,该消息将字节数据解码为 class 成员 - 这占所有流量的大约 95%。

我是 c#-dotNet 的新手,我在 C++ 方面有很多经验,管理它的旧方法是拥有一个字段端点数组,这些端点可以存储对我可以增长的数据结构的引用在接收端重建消息时需要。我已经研究了 C# 等效方法的可能方法,但它们似乎是面向 HTTP 的,并且使用文件系统进行临时存储,但我正在寻找一种在内存中构建消息的方法。我对 C# classes、持久性、垃圾 collection 等的掌握仅限于我不确定方法的程度。

我的 TCP 处理程序有一个回调消息处理程序,它为 'abc' 协议解析消息:

void processTcpPacket(StateObject tcpControl)
{
    abcMessage abc = new abcMessage();
    abc.parse(tcpControl.buffer,tcpControl.size)
    if(abc.complete)
    {
        do something with this message()
    }else if abc.multipart{
        hold this message somewhere until the next part shows up... ?
    }else{
        discard unparseable message()
    }
}

processTcpPacket() 是异步的,并从许多端点传递消息;每条消息中的 headers 都有完整的源地址和目标地址。该协议会将一条长消息分成大约 200 字节的段,然后发送给接收方并重新组合 - 最大有效载荷可达 ~5000 字节。

在C++的世界里,我会为multipart messages创建一个存储容器,里面有sendee的源地址,这样我就可以找到合适的容器,不断添加message parts直到消息完成,然后处理消息并删除临时容器。我可以使用 C# 执行类似的过程吗?

Unless I'm missing the point, neither of these allows me to create an object to 'remember' the partial data until the next asynchronous callback. This object has to persist outside the callback...

正确...在 Class 级别声明字典,以便它在调用中持续存在,并使用源地址作为键添加“abc”实例。

这是一些非常粗略的伪代码:

Dictionary<sourceAddress, abcMessage> msgs = new Dictionary<sourceAddress, abcMessage>();

void processTcpPacket(StateObject tcpControl)
{
    if (msgs.ContainsKey(sourceAddress))
    {
        abcMessage abc = msgs[sourceAddress]; // pull partial from the dictionary
        abc.AddParse(tcpControl.buffer,tcpControl.size); // do you have a way to ADD a message yet?
        if(abc.complete)
        {
            do something with this message()
        }
        // if partial, it's already stored in the dictionary, leave it there
    }
    else
    {
        abcMessage abc = new abcMessage();
        abc.parse(tcpControl.buffer,tcpControl.size)
        if(abc.complete)
        {
            do something with this message()
        }else if abc.multipart{
            msgs.Add(sourceAddress, abc); // hold this message somewhere until the next part shows up... ?              
        }else{
            discard unparseable message()
        }
    }
}

不确定要将 "sourceAddress" 键类型存储为什么。它可以是 IP 的字符串形式,或其他一些唯一标识来源的方式。