C# .NET核心串行类在使用tty端口发布到Linux计算机时,未读取BaseStream或ReadBuffer中超过4KB的数据
我构建了一个串口文件传输.NET CORE 3.0应用程序,它在windows中运行良好,但在linux上只能读取少量数据。基本上,我从一台机器传输数据,而接收机器读取的数据如下:C# .NET核心串行类在使用tty端口发布到Linux计算机时,未读取BaseStream或ReadBuffer中超过4KB的数据,c#,linux,.net-core,serial-port,embedded,C#,Linux,.net Core,Serial Port,Embedded,我构建了一个串口文件传输.NET CORE 3.0应用程序,它在windows中运行良好,但在linux上只能读取少量数据。基本上,我从一台机器传输数据,而接收机器读取的数据如下: _serialPort.ReadBufferSize = 7000000; ...more setup code Console.WriteLine("Serial receiver started at " + DateTime.UtcNow.ToString("yyyy-MM-
_serialPort.ReadBufferSize = 7000000;
...more setup code
Console.WriteLine("Serial receiver started at " + DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture) + " Collecting and decoding file data for 4 minute intervals. Please wait...");
Console.WriteLine("Header search pattern: " + BitConverter.ToString(BitConverter.GetBytes(header)));
int sleepTimeMiliseconds = (240000 - (int)stopwatch.Elapsed.TotalMilliseconds < 1) ? 0 : 240000 - (int)stopwatch.Elapsed.TotalMilliseconds;
Thread.Sleep(sleepTimeMiliseconds); // wait for about 4 minutes for the data to come in.
byte[] dataBuffer = new byte[_serialPort.ReadBufferSize];
//read data then discard buffer to get new data from the transmitting machine
if (!_serialPort.IsOpen) // serial port could close when operating system sleeps
_serialPort.Open();
_serialPort.Read(dataBuffer, 0, dataBuffer.Length);
//HundredKBBuffer = Convert.FromBase64String(_serialPort.ReadExisting());
_serialPort.DiscardInBuffer();
stopwatch.Restart();
Console.WriteLine("Data buffer size in bytes: " + dataBuffer.Length);
DecodeFileData(dataBuffer, header, trailer);
\u serialPort.ReadBufferSize=7000000;
…更多设置代码
Console.WriteLine(“串行接收器在”+DateTime.UtcNow.ToString(“yyyy-MM-dd HH:MM:ss.fff”,CultureInfo.InvariantCulture)+“每隔4分钟收集和解码文件数据。请稍候…”);
WriteLine(“标题搜索模式:+BitConverter.ToString(BitConverter.GetBytes(标题)));
int sleeptimemilyseconds=(240000-(int)stopwatch.appeased.totalmilyseconds<1)?0:240000-(int)stopwatch.appeased.total毫秒;
Thread.Sleep(睡眠时间毫秒);//等待大约4分钟,以便数据进入。
字节[]数据缓冲=新字节[_serialPort.ReadBufferSize];
//读取数据,然后丢弃缓冲区,从传输机器获取新数据
if(!\u serialPort.IsOpen)//当操作系统休眠时,串行端口可能会关闭
_serialPort.Open();
_读取(dataBuffer,0,dataBuffer.Length);
//hundredkbuffer=Convert.FromBase64String(_serialPort.ReadExisting());
_serialPort.DiscardInBuffer();
stopwatch.Restart();
WriteLine(“以字节为单位的数据缓冲区大小:“+dataBuffer.Length”);
DecodeFileData(数据缓冲、头文件、尾文件);
我还尝试了使用
\u serialPort.BaseStream.Read(dataBuffer,0,dataBuffer.Length)
而不是\u serialPort.Read(dataBuffer,0,dataBuffer.Length)代码>但同样的问题也会发生。我从未在缓冲区中看到超过4096的字节,因此我不确定如何在linux环境中实现这一点。缓冲区大小是否更小且不可更改?我使用了\u serialPort.ReadBufferSize=7000000代码>但它似乎对问题没有帮助。linux机器是CentOS或Redhat4KB是tty缓冲区的限制。内核有一个4096字节的内部缓冲区。如果此缓冲区已满且新字节到达串行端口,则缓冲区中最早的字节将被覆盖,从而丢失
我解决了.NET CORE 3.0不允许我设置_serialPort.ReadBufferSize的问题,基本上是通过使用“流字节读取器”方法,并将当前索引沿自定义字节[]缓冲区递增多少字节,不管在以前的读取操作中读取了多少字节(轮询以填充自定义缓冲区)
byte[]dataBuffer=新字节[3000000];//足够大的缓冲区
bool singleReadIterationFinished=false;
而(!singleReadIterationFinished)
{
Task bytesReadFromPort=\u serialPort.BaseStream.ReadAsync(dataBuffer,bufferOffset,dataBuffer.Length-bufferOffset);//一次读取尽可能多的可用字节
//由于线程没有被阻塞,其他代码可以转到这里
bufferOffset+=ByteReadFromPort.Result;//来自docs.Microsoft:调用结果属性get访问器将阻止调用线程,直到异步操作完成;这相当于调用“Wait”方法。
if(bufferOffset>2000000)//等待2M兆字节的数据。将其更改为MB。
{
WriteLine(“读取总共:“+bufferOffset+”字节”);
byte[]copyBuffer=新字节[dataBuffer.Length];
Copy(dataBuffer,0,copyBuffer,0,dataBuffer.Length);
DecodeFileData(copyBuffer、header、traile);//需要异步调用它
singleReadIterationFinished=true;
}
}
Linux上的串行端口似乎仍然有缺陷。你的问题可能会使它雪上加霜,
byte[] dataBuffer = new byte[3000000]; // big enough buffer
bool singleReadIterationFinished = false;
while (!singleReadIterationFinished)
{
Task<int> bytesReadFromPort = _serialPort.BaseStream.ReadAsync(dataBuffer, bufferOffset, dataBuffer.Length - bufferOffset); // read as many bytes as available at a time
//other code can go here since the thread isn't blocked
bufferOffset += bytesReadFromPort.Result; // From docs.Microsoft: Calling the result properties get accessor will block the calling thread until the asyncrhonous operation is complete; this is equivalent to calling 'Wait' method.
if (bufferOffset > 2000000) // wait for 2megabytes of data. change this to megabytes.
{
Console.WriteLine("Read a total of : " + bufferOffset + " Bytes");
byte[] copyBuffer = new byte[dataBuffer.Length];
Array.Copy(dataBuffer, 0, copyBuffer, 0, dataBuffer.Length);
DecodeFileData(copyBuffer, header, trailer); // need to call this asyncronously
singleReadIterationFinished = true;
}
}