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

Matlab: TCP Connection Fread data Size Warning Error

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

警告:指定数量的数据未在超时期限内返回。 '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'),但它给了我错误。有谁知道如何绕过这个警告?

您正在尝试从 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 对象,但图形对象工作相同)和 evt 一个包含有关事件的数据的结构(例如 IP/port 来自消息的来源;对于将是键和修饰符的 KeyPress 事件)。

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

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

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

和回调:

function myTcpipCallback(obj,evt)
    % Bufferize
    obj.UserData=[obj.UserData ; fread(obj,1,'char')]; %Read 1 byte

    % Check if the message if known
    msg = obj.UserData;
    if isComplete(msg)  % 
         obj.UserData=[]; % empty buffer
         processMessage(msg); % do something with message
    end
end