1

我是使用套接字的新手。我有一个非常基本的客户端,它发送请求并等待响应。响应是一个流,但有两个部分。第一部分以 ANS 为前缀,是一组采用以下形式的键/值对:KEY:Value,每对位于单独的行上。

响应的第二部分以 RCT 为前缀,这是需要直接发送到打印机的预格式化文本。

那么提取响应的两个部分的最佳方法是什么,并且在第一部分中,获取每个 Key:Value 对。我什至可能都不需要它们,但我必须查看每一个以查看值是什么,然后决定如何处理它。

我目前正在将响应写入文本框只是为了了解它在做什么,但现在我需要对数据进行实际操作。

这是收到的数据样本:

ANS Result: Data Received                                                                
RCPRES:Q[81]
TML:123
OPP:
MRR:000000999999
<several dozen more KEY:Value pairs>
RCTNov 05 2013  04:03 pm      Trans# 123456

           <pre-formatted text>
4

2 回答 2

1

将溪流想象成一条传送带,带有一个装有物品的门。因此,当其他一些人进一步添加内容时,您最终会在大门后面有一个缓冲区。在你的大门后面的某个地方还有一个传感器,它会向另一个人发出信号,让他们停止把东西放在线上。您不必知道该传感器有多远。另一个人可能会非常快地添加项目(直到他被传感器发出暂停信号)或者他可能会慢慢地添加它们。

您可以通过调用 .Peak() 检查门后备份的项目数量。您还可以通过调用 .Read() 离线读取(让通过门)一个或多个框

读取一个字节将是一个盒子,读取一个 int 将是 4 个盒子;因为 int 是 4 个字节长。或者你可以读取一个(比如说)4个整数的数组,这将是16个盒子/字节

(在我的脑海中,我认为如果您要求读取比缓冲区中更多的数据,那么它要么阻塞(等待更进一步的人发送更多的盒子,或者它抛出一个异常......你会需要试试看)

好的,现在为您的数据。你很容易。每个键值对用新行分隔。您可以做的是读取一个字节并将其转换为字符并检查它是否为新行字符,如果不将其添加到缓冲区以在最终找到一个字符串时转换为字符串。

然而,这是混乱和低效的。您可以做的是创建一个实现 TextReader 的阅读器,例如,使用您的内存流的StreamReader 。

StreamReader 实现了一个 ReadLine() 方法,它将为您执行此操作。

好的,现在在 while 循环中从您的套接字/StreamReader 中逐行读取。然后检查每一行是键值对还是 RCT 东西

如果是KVP,添加到List,或者在冒号上拆分,添加到Dictionary;或类似的东西,以备后用

如果是 RCT,则调用 ReadToEnd() 连接两个字符串(RCT 到换行符和 ReadToEnd)并将其传递给您的打印机。

您还将在开始时做一些事情来说明 ANS。说使用Read(Char[], Int32, Int32)重载。

于 2013-11-06T03:53:12.243 回答
1

考虑到缓冲区已经完全加载到内存中后您正在使用它,您希望的最好结果就是高效的数组操作。据我所知,MemoryStream该类只不过是Stream内存中字节数组的外观(当然,添加了适当的定位处理)。

您最好以最小的显着增量迭代流,因此假设您的示例文本是真实的,并且取决于新行是 CR、LF 还是 CR + LF,它可能是一个或两个字节。迭代直到找到您期望的 RCT 前缀(假设在流中的其他地方找不到该序列)应该允许您假设您仍在处理 KV 对并做出相应的响应。

一旦达到 RCT 前缀,您似乎需要切换到特定于您的实现的固定宽度处理方法。

就该系统的高级设计而言,我可能会推荐一个捕获/状态对象,该对象能够从消息中表示每个不同的可能 KV 对(假设固定值仍然具有关联的隐式键)。您需要至少 2 个不同的解析器来根据所需格式处理请求;一个用于 KEY:VALUE 格式的显式 KV 对,另一个用于强格式部分的隐式 KV 对。有了这些,只需迭代流字节并根据消息的“阶段”将消息的部分委派给每个解析器。

于 2013-11-06T04:20:03.857 回答