我有一个帖子。在他们内部,我有一个发送UDP数据包的循环。在此循环中,我需要等待设备的UDP响应(接收到先前的数据包[如果正常或不存在]),然后发送下一条消息。如果确定我发送StringList的下一条消息,如果错误我停止线程。怎么做?我需要更多:如果软件没有收到设备的响应,我需要实现3秒的超时。
我使用TIdUDPServer来监听udp包。
这是我的代码:
TEnvioFirmware = class(TThread)
private
I: integer;
Lock: TCriticalSection;
mMac: string;
mVersao: integer;
mProduto: integer;
_max: integer;
_min: integer;
mIP: string;
firmware_string: TStringList;
idpclnt: TIdUDPClient;
progress: TProgressBar;
lbPorc: TLabel;
bAck: Boolean;
procedure Executar;
procedure OnVerificarTimeOut(Sender: TObject);
public
tmrTimeout: TTimer;
bContinua: Boolean;
procedure Execute; override;
constructor Create(CreateSuspended: Boolean; firmware_string: TStringList;
edtIP: string; idpclnt: TIdUDPClient; max, atual: integer;
var pb: TProgressBar; var lblPorcentagem: TLabel; abAck: Boolean);
end;
procedure TEnvioFirmware.Execute;
begin
inherited;
// Synchronize(Executar);
Executar;
end;
procedure TEnvioFirmware.Executar;
var
I, J: integer;
X: pacote;
Y: String;
B: String;
B2: String;
msgCount: integer;
Buffer: TBytes;
// array[0..5] of Byte;
max, atual: integer;
BufferSend: TBytes;
begin
SetLength(Buffer, 6);
idpclnt.Host := mIP;
idpclnt.Active := true;
msgCount := firmware_string.Count;
max := msgCount - 1; // Progress Bar
// pb.Max := max;
self.progress.Min := 0;
self.progress.max := max;
B := '12345';
B2 := '0';
if bAck then
begin //trying to make timeout
tmrTimeout := TTimer.Create(nil);
tmrTimeout.Interval := 3000;
tmrTimeout.OnTimer := OnVerificarTimeOut;
end;
bContinua := True;
for I := 0 to msgCount - 1 do
begin
B[1] := chr(15);
B[2] := chr(0);
B[3] := chr(2);
B[4] := chr((I) mod 256);
B[5] := chr((I) div 256);
B2[1] := chr(255);
Y := B + firmware_string.Strings[I] + B2;
SetLength(BufferSend, Length(Y));
for J := 0 to Length(BufferSend) - 1 do
begin
BufferSend[J] := Ord(Y[J + 1]);
end;
if bContinua then
idpclnt.SendBuffer(BufferSend); //after send the device will response
if not bAck then
begin
Sleep(200);
bContinua := true;
progress.Position := I + 1;
lbPorc.Caption :=
IntToStr(Round((100 * progress.Position) / progress.max));
atual := I;
end
else
begin
tmrTimeout.Enabled := True;
end;
end;
Buffer[0] := $0F;
Buffer[1] := 00;
Buffer[2] := 03;
Buffer[3] := (msgCount) mod 256;
Buffer[4] := (msgCount) div 256;
Buffer[5] := 255;
idpclnt.SendBuffer(Buffer);
Sleep(150);
end;
在UDPRead上
if (AData[0] = 15) and (AData[1] = 1) and (AData[2] = 2) and (Count = 5)
then
begin
if AData[3] = 0 then
begin
MainEstrutura.objFirmwareUpdater.bContinua := true;
MainEstrutura.objFirmwareUpdater.tmrTimeout.Enabled := false;
end
else
begin
MainEstrutura.objFirmwareUpdater.bContinua := false;
MainEstrutura.objFirmwareUpdater.tmrTimeout.Enabled := false;
end;
end;
答案 0 :(得分:2)
由于您需要序列化数据包,因此应在线程内部使用TIdUDPClient
,而不是在线程外部使用TIdUDPServer
。然后,您不必处理同步OnUDPRead
事件或完全使用计时器。只需将线程SendBuffer()
作为传出数据包,然后立即ReceiveBuffer()
指定超时的入站响应,并根据需要继续循环直到完成。如果超时,则重新发送出站数据包,或终止线程,具体取决于您的需要。
在这种情况下使用TIdUDPServer
的唯一原因是,如果您有多个固件线程同时运行并且它们都响应相同的IP /端口,在这种情况下,有一个是有意义的单TIdUDPServer
接收所有这些响应,并根据需要将它们分配到每个适当的固件线程。