我需要解析一个包含协议定义的二进制格式化消息的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++世界中,我将为多部分消息创建存储容器,该多个消息具有参议员的源地址,因此我可以找到正确的容器,并在消息完成之前一直添加消息部分,然后处理消息并删除临时容器。我是否可以遵循与C类似的流程?
最佳答案
除非我漏掉了重点,否则这两个都不允许我创建
对象以“记住”部分数据,直到下一个异步
回拨。此对象必须保留在回调之外…
好的……在类级别声明字典,这样它就可以在调用之间持续存在,并使用源地址作为键添加“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的字符串形式,也可以是唯一标识源的其他方式。