在超时后阻止来自C#NetworkStream的传入数据

问题描述 投票:0回答:1

我有一个奇怪的问题,涉及C#.Net Core 2.2.101中的NetworkStreams

我的设置如下:

  • 我有一个的列表
  • 每个仪表都有寄存器的列表(寄存器保存一个值,例如:电压或电流)
  • 仪表通过RS485连接到GSM调制解调器(与问题无关)
  • 我发送命令到调制解调器以读取特定电表的特定寄存器

对于每个仪表的每个寄存器,我使用stream.Write(bytesToSend, 0, bytesToSend.Length);发送命令,要求仪表将保存在仪表特定寄存器中的数据发送给我。发送后,我立即使用stream.Read(buffer, 0, buffer.Length);读取了响应。我还将read超时设置为5秒,如果在超时之前未收到响应,它将阻塞并等待5秒钟,然后再进入下一个寄存器。

问题:

发生的情况是,当我向电表查询数据时,有时会花费太长时间并且达到超时,此后,我将继续向下一个寄存器查询数据,但是有时第一个寄存器会答复在我移至下一个寄存器之后,获取数据(这意味着NetworkStream现在具有来自先前寄存器的数据)。由于我已经进入for循环,因此程序认为从流中读取的数据用于当前寄存器,而实际上是用于先前迭代中的先前寄存器。这会弄乱进入数据库的数据,因为我为错误的寄存器保存了错误的值。

我的问题是:是否有一种聪明的方法可以忽略for循环中先前迭代的任何传入数据?

不幸的是,接收到的数据中没有任何信息可用于标识哪个寄存器数据用于。

这里是我的读写请求的摘要:

stream.ReadTimeout = 5000;
stream.WriteTimeout = 2000;

foreach (Meter meter in metersToRead)
{
  foreach (Register register in meter.Registers)
  {
    // Write the request to the meter
    stream.Write(bytesToSend, 0, bytesToSend.Length);

    // Read response from meter
    requestedReadingDataCount = stream.Read(buffer, 0, buffer.Length);

    // Extract the value from the response buffer and save the value to the database
    ...
  }
}

我想尝试克隆流,并使用克隆的流进行有关当前寄存器迭代的通信,因此,当我关闭克隆的流并移至下一个寄存器后出现响应时,响应将失败,因为流已关闭。 但是,我不确定是否可以克隆C#NetworkStream?有人知道吗?

我的最后一招是在读取每个寄存器的数据后调用数据库,以检查接收到的数据对于该寄存器是否合理,但是我担心这可能会使所有数据库的程序运行变慢调用,我将必须建立一些规则来确定某个值对于当前寄存器是否合理。

任何想法都将不胜感激。如果您有任何疑问,请告诉我,我将尽力进一步解释。

[我在C#.Net Core 2.2.101中有一个涉及NetworkStreams的奇怪问题,我的设置如下:我有一个仪表列表每个仪表都有一个寄存器列表(一个寄存器为...保存一个值)>

c# asp.net-core modbus networkstream
1个回答
1
投票

听起来这里的问题是,在超时情况下,读操作在将来的某个时候仍会完成,但会写入旧缓冲区。在这种情况下,也许最简单的选择是在超时的情况下不重用读取缓冲区(这意味着:将新的byte[]分配给buffer),并考虑网络流已烧坏(因为您现在可以不知道内部状态是什么。

另一种方法是直到知道数据才读

© www.soinside.com 2019 - 2024. All rights reserved.