Hello! First, a deepfelt thank you for all of your wonderful work on Indy.
It ROCKS! I am using it to talk to image generators in flight simulators. I
am using the UDP protocol. I have two fixes that I humbly suggest you add.
In particular, I have found that the UDP components will fail (and stay
failed) if you try to read from a socket before it is present. What happens
is that the read returns -1 (not zero bytes) and once it does, the component
will not work. I have made the following changes:
**** In IDUDPBASE.PAS (changes are surrounded by my initials MDC) ****
function TIdUDPBase.ReceiveBuffer(var ABuffer; const ABufferSize: Integer;
var VPeerIP: string; var VPeerPort: integer;
AMSec: Integer = IdTimeoutDefault): integer;
begin
if AMSec = IdTimeoutDefault then
begin
AMSec := ReceiveTimeOut;
end;
if not Binding.Readable(AMSec) then
begin
Result := 0;
VPeerIP := '';
VPeerPort := 0;
Exit;
end;
Result := Binding.RecvFrom(ABuffer, ABufferSize, 0, VPeerIP, VPeerPort);
{ MDC }
if Result < 0 then { MDC }
exit; { MDC }
{ MDC }
GStack.CheckForSocketError(Result);
if Result = 0 then
begin
raise EIdUDPReceiveErrorZeroBytes.Create(RSUDPReceiveError0);
end;
end;
**** Next change ****
**** In IDUDPSERVER.PAS (changes are surrounded by my initials MDC) ****
procedure TIdUDPListenerThread.Run;
var
PeerIP: string;
i, PeerPort, ByteCount: Integer;
FReadList: TList;
begin
FReadList := TList.Create;
try
FReadList.Capacity := FServer.Bindings.Count;
for i := 0 to FServer.Bindings.Count - 1 do
begin
FReadList.Add(Pointer(FServer.Bindings[i].Handle));
end;
GStack.WSSelect(FReadList, nil, nil, AcceptWait);
for i := 0 to FReadList.Count - 1 do
if not Stopped then
begin
IncomingData :=
FServer.Bindings.BindingByHandle(TIdStackSocketHandle(FReadList[i]));
FBuffer.SetSize(FBufferSize);
ByteCount := GStack.WSRecvFrom(IncomingData.Handle, FBuffer.Memory^,
FBufferSize, 0
, PeerIP, PeerPort);
{ MDC }
if ByteCount < 0 then { MDC }
exit; { MDC }
{ MDC }
GStack.CheckForSocketError(ByteCount);
if ByteCount = 0 then
begin
raise EIdUDPReceiveErrorZeroBytes.Create(RSUDPReceiveError0);
end;
FBuffer.SetSize(ByteCount);
FBuffer.Position := 0;
IncomingData.SetPeer(PeerIP, PeerPort);
if FServer.ThreadedEvent then
begin
UDPRead;
end
else
begin
Synchronize(UDPRead);
end;
end;
finally
FReadList.Free;
end;
end;
Can you please give me your opinion? After these changes, I was able to use
the components properly. In my case, I could never be sure which end would
"come up" first. If I did not have this change, the component would fail and
not recover when the other end DID come alive.
Thank you for your time,
Michael Christopher
Software Engineer
Kettering OH USA
savvys...@woh.rr.com