问题遇到的现象和发生背景
我在手写modbus通信库的时候遇到一个问题
在我发送求情数据的命令以后,返回的数据会自动缓存到缓存区,等待我从缓存区取数据。
我开启一个while循环,每隔20毫秒判断一次缓存区返回数据长度大于0就取,不然就退出,会不会取不完整?
万一数据已经取了一部分但没有取完,这时候又判断了一次,但已经取过的数据会被缓存区的引用指针给无视掉,就不会被检测了,这时候我剩下的数据还没来得及到缓存区,我的判断就已经执行了,判断数据长度被判断为0,但接收数据的变量已经被判断有数据,不就取不完整了?
下面是代码(这个是根据网络教程写的)
串行端口对象(SerialPort)来自于命名空间System.IO.Ports
Mycom变量是已经配置好的串行端口对象
stream是内存流(MemoryStream)对象
data是字节数组
ReceiveTimeOut是我设置的终止时间
问题相关代码,请勿粘贴截图
//使用一个while循环不断尝试接收返回的数据
while (true)
{
//每二十毫秒检测一次缓冲区
Thread.Sleep(20);
//如果返回到缓冲区的数据大于0就接收到内存流,(获取接收缓冲区数据的字节数)
if (Mycom.BytesToRead>0)
{
//读取从com口返回到缓冲区的返回字节,存到指定的字节数组
int count = Mycom.Read(data,0,data.Length);
//将有效数据存储到内存流
stream.Write(data,0,count);
}
//判断是否超时(起始时间和已经执行的时间的时间差大于两秒)
else
{
if ((DateTime.Now - strat).TotalMilliseconds >= this.ReceiveTimeOut)
{
//两秒还没有读到就释放内存流,返回空值
stream.Dispose();
return null;
}
//如果缓存区数据等于0,并且内存流已经有了数据
else if (stream.Length>0)
{
break;
}
}
}
运行结果及报错内容
我的解答思路和尝试过的方法
是不是我理解错了呢?我自己搜索的结果,理论上有三种解决方案
1.缓存锁(我有点不明白用C#怎么写缓存锁)
2.直接sleep等待,因为modbus的返回数据长度通常只有不到15个字节,等待时间并不长
3.直接数据异常校验,因为返回的数据长度是能预测的(但是这样我感觉并没有根源上解决问题)
我想要达到的结果
最后我还想知道,到底哪些数据流是由缓存区的,哪些数据流是没有缓存区的,据我所了解的,socket通信的数据流似乎并没有缓存区的概念