Matlab:TCP连接读取数据大小警告错误

时间:2018-11-04 13:51:02

标签: matlab warnings fread

我的Matlab代码中有一个TCP服务器,我的客户端在某些触发器上将一些数据(最大4个字节)从另一个应用程序发送到Matlab。我收到这些号码,但也多次收到此警告消息:

警告:超时时间内未返回指定的数据量。 'tcpip'无法读取所有请求的数据。有关可能原因的更多信息,请参见TCPIP阅读警告。

clc;
t = tcpip('0.0.0.0', 55000,'InputBufferSize', 1024,'NetworkRole','Server', 'TimeOut', 0.5);
fopen(t);
while(1)    
    data = fread(t, 4, 'char');    
    dataChar = char(data);
    dataDouble = str2double(dataChar);  
      if (~isnan(dataDouble))
          if (dataDouble == 0)
              fclose(t); % closing the tcp connecting
              error('0 value is received!') % to jump out of Matlab run mode
          else
              disp("Last Receieved double was: " + dataDouble)
          end       
      end       
  end

我也尝试了get(obj1,'BytesAvailable'),但它给了我错误。有人知道如何绕过此警告吗?

1 个答案:

答案 0 :(得分:0)

您正在尝试从tcpip对象中读取数据,而不读取数据(即缓冲区已经为空)。 Matlab将等待一段时间,看看是否有任何问题,然后发出警告。 使用tcpip obj的正常方法是在某个事件上执行回调,然后使用该回调从缓冲区读取数据。

有两种模式:找到特定终止符(例如换行,如果读取文本)时触发缓冲区,或者接收到一定数量的字节时触发

假设所有消息的字节长度为4,则语法为:

t = tcpip('0.0.0.0', 55000,'InputBufferSize', 1024,'NetworkRole','Server', 'TimeOut', 0.5);
t.BytesAvailableFcnCount = 4;     % n=4
t.BytesAvailableFcnMode = 'byte'; %Read after n bytes have been received
t.BytesAvailableFcn     = @myTcpipCallback;
fopen(t);

每收到4个字节,就会调用一次回调。回调函数的语法为:

function myTcpipCallback(obj,evt)
    data=fread(obj,4,'char'); %Read 4 characters
    % ... do something with data ... %
    if bad_data_received==true
         fclose(obj);
    end
end

while循环不是必需的,它已经由tcpip对象在内部处理。回调函数的语法遵循Matlab标准callbackFunction(obj,evt),其中obj是触发回调的事件发生的对象(此处是tcpip对象,但是图形对象的工作原理相同)和{{1} }包含有关事件的数据的结构(例如,消息所来自的IP /端口;对于将作为键和修饰符的KeyPress事件)。

您写道,另一个应用程序上的客户端将发送最多4个字节。固定字节数(可以通过在客户端填充消息来实现)确实更方便,或者,如果进行了按摩,则应使用一些终结符来标记结束。

使用终止符(例如,每条消息以换行符结尾),语法为:

evt

和回调

t.BytesAvailableFcnMode = 'terminator';
t.Terminator = char(10);     % or newline or recent versions of Matlab

如果客户端快速发送数据,则可能在回调函数在队列中等待时缓冲了一些额外的数据,因此,在执行该功能时,可能会有几条消息可用。该代码应考虑到这种可能性。不幸的是,触发回调后缓冲区中可用的字节数不在事件数据中。

最后,如果您打算接收具有复杂规则的任意长度的消息以确定其是否完整,则另一种可能性是逐个读取字节并在某个地方拥有自己的缓冲区,例如在对象用户数据中。

function myTcpipCallback(obj,evt)
    data=[obj.UserData ; fread(obj,obj.BytesAvailable,'char')]; %Read all available characters
    %Just in case, check that we have not received more than one message
    term=[0;find(data==obj.Terminator)];
    for ii=1:length(term)-1
       msg=data(term(ii)+1:term(ii+1));
       %Do something with msg%
    end
    obj.UserData=data(term(ii)+1:end);
end

和回调:

t.BytesAvailableFcnCount = 1;     % n=1
t.BytesAvailableFcnMode = 'byte'; %Read after n bytes have been received