Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET核心串行类在使用tty端口发布到Linux计算机时,未读取BaseStream或ReadBuffer中超过4KB的数据_C#_Linux_.net Core_Serial Port_Embedded - Fatal编程技术网

C# .NET核心串行类在使用tty端口发布到Linux计算机时,未读取BaseStream或ReadBuffer中超过4KB的数据

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-

我构建了一个串口文件传输.NET CORE 3.0应用程序,它在windows中运行良好,但在linux上只能读取少量数据。基本上,我从一台机器传输数据,而接收机器读取的数据如下:

        _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或Redhat

4KB是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;
                        }
                    }