Вы пытаетесь прочитать данные из объекта 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 / порт, откуда приходит сообщение; для события 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
Если клиент отправляет данные быстро, некоторые дополнительные данные могли быть буферизованы, пока функция обратного вызова ожидала в очереди, поэтому к моменту ее выполнения может быть доступно несколько сообщений. Код должен учитывать эту возможность. К сожалению, количество байтов, доступных в буфере при запуске обратного вызова, отсутствует в данных события.
Наконец, если вы намереваетесь получать сообщения произвольной длины со сложными правилами, чтобы определить, завершен он или нет, другой возможностью является чтение байтов один за другим и где-нибудь иметь свой собственный буфер, например, в объекте userdata.
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