【问题标题】:multipart message stream handling in C#C# 中的多部分消息流处理
【发布时间】:2015-10-25 18:52:30
【问题描述】:

我需要解析包含协议定义的二进制格式消息的 TCP 数据流,这些消息可能是多部分的,也可能不是多部分的。消息中的标题指示消息是否包含多个部分(第 1 部分,共 4 部分等)。我正在使用将字节数据解码为类成员的消息类成功解析单部分消息 - 这约占所有流量的 95%。

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

我的 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() 是异步的,从多个端点传递消息;每条消息的标头都有完整的源地址和目标地址。该协议将一条长消息分成大约 200 个字节的段,然后发送到接收器并重新组合 - 最大的有效载荷可达约 5000 个字节。

在 C++ 世界中,我会创建一个包含 sendee 源地址的多部分消息的存储容器,这样我就可以找到正确的容器并不断添加消息部分,直到消息完成,然后处理消息并删除临时容器。我可以使用 C# 遵循类似的过程吗?

【问题讨论】:

  • 当然,您正在寻找Dictionary,它允许您根据键查找存储一些内容。
  • 也许你想看看this example。它使用 NewLine char 作为数据包分隔符,使用 json 作为数据包容器。
  • 除非我没有抓住重点,否则这些都不允许我创建一个对象来“记住”部分数据,直到下一次异步回调。该对象必须在回调之外持续存在...
  • 对...在类级别声明字典,以便它在调用中保持不变,并使用源地址作为键添加“abc”实例。

标签: c# parsing tcp persistence


【解决方案1】:

除非我没有抓住重点,否则这些都不允许我创建一个 对象“记住”部分数据,直到下一次异步 打回来。该对象必须在回调之外持续存在...

对...在类级别声明字典,以便它在调用中保持不变,并使用源地址作为键添加“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 的字符串形式,也可以是其他方式来唯一标识来源。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    • 2019-06-21
    相关资源
    最近更新 更多