【发布时间】:2015-06-13 18:48:30
【问题描述】:
在我的应用程序中,我必须从通过 COM 端口连接的设备接收和处理一些数据。我部分地做。在该特定设备中,前两个字节是数据包的长度(减 2,因为它没有考虑这两个字节;所以它毕竟是数据包其余部分的长度)。然后,由于我知道设备倾向于缓慢地向我发送数据,我在循环中读取数据包的其余部分,直到所有数据都被读取。但是在这里我遇到了奇怪的问题。让我们假设整个数据包(包括前两个字节的长度)如下所示:['a', 'b', 'c', 'd', 'e']。当我读取前两个字节('a' 和 'b')时,我希望数据包的其余部分看起来像这样:['c', 'd', 'e']。但相反,它看起来像这样:['b', 'c', 'd', 'e']。为什么响应的第二个字节仍在读取缓冲区中?为什么只有第二个,没有前一个?
下面的代码显示了我如何处理通信过程:
//The data array is some array with output data
//The size array is two-byte array to store frame-length bytes
//The results array is for device's response
//The part array is for part of the response that's currently in read buffer
port.Write(data, 0, data.Length);
//Receiving device's response (if there's any)
try
{
port.Read(size, 0, 2); //Read first two bytes (packet's length) of the response
//We'll store entire response in results array. We get its size from first two bytes of response
//(+2 for these very bytes since they're not counted in the device's data frame)
results = new byte[(size[0] | ((int)size[1] << 8)) + 2];
results[0] = size[0]; results[1] = size[1]; //We'll need packet size for checksum count
//Time to read rest of the response
for(offset = 2; offset < results.Length && port.BytesToRead > 0; offset += part.Length)
{
System.Threading.Thread.Sleep(5); //Device's quite slow, isn't it
try
{
part = new byte[port.BytesToRead];
port.Read(part, 0, part.Length); //Here's where old data is being read
}
catch(System.TimeoutException)
{
//Handle it somehow
}
Buffer.BlockCopy(part, 0, results, offset, part.Length);
}
if(offset < results.Length) //Something went wrong during receiving response
throw new Exception();
}
catch(Exception)
{
//Handle it somehow
}
【问题讨论】:
-
哦,当我第二次读取时(即当我得到那个旧字节时),port.BytesToRead 也意味着还有一个字节。我的意思是,如果数据包总共有 x 个字节并且我读取了前两个字节,则 port.BytesToRead == x - 1 而不是 x - 2。
-
如果这么慢,那么在读取前两个字节后执行“port.DiscardInBuffer()”。
-
它实际上让一切变得更糟。
-
不能忽略 Read() 的返回值。它是 1,而不是 2。
标签: c# serial-port buffer