Board index » delphi » Team Indy, Please read.

Team Indy, Please read.

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

 

Re:Team Indy, Please read.


ha ha, I beat Team Indy to this one :-)  (probably not by the time I finish
witing this message.)

I bet I know what they're gonna say......

What version of indy are you running?   You can get the very latest version
of the Indy 9 BETA from  ftp://indy90:ind...@ftp.nevrona.com/

Update your code to this, then try again.

If it still doesn't work then post the code changes into their bug reporting
system.  You can get it at http://www.nevrona.com/indy/ and follow the
"Report a bug" link.

and you're right INDY does rock, big style.

Regards

Colin Dawson.

Quote
"michael christopher" <savvys...@woh.rr.com> wrote in message

news:3c23e468_1@dnews...
Quote
> 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

Re:Team Indy, Please read.


Quote
michael christopher wrote:
> **** 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;

Thank you for your comments.

First off, the new Indy (starting with 8.1 beta I think) doesn't check
for Result=0. You're now allowed to send/receive an empty packet.

Secondly, Win32.hlp states:
"(...)Otherwise, a value of SOCKET_ERROR is returned, and a specific
error code can be retrieved by calling WSAGetLastError."

Which is exactly what GStack.CheckForSocketError does... (atleast the
version I'm looking at now)

So the question becomes: What exception is raised?

Quote
> "come up" first. If I did not have this change, the component would fail and
> not recover when the other end DID come alive.

Sounds strange. Are they running on the same machine? What operating
systems are you using?

--
Rune

Other Threads