我的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'),但它给了我错误。有人知道如何绕过此警告吗?
答案 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