Article

From:
To:
Remy Lebeau (TeamB)
Subject:
Re: TIdIPMCastClient difficulties [Edit] [Edit]
Newsgroup:
embarcadero.public.delphi.internet.winsock

Re: TIdIPMCastClient difficulties [Edit] [Edit]

> {quote:title=Remy Lebeau (TeamB) wrote:}{quote}
> > So I was studying the multicast RFC 1112 and Steve Deering's articles
> > on the subject, and I must conclude that the Indy implementation (or
> > at least what you say in your earlier response to me) is not really
> > correct.
> 
> I assure you, it is.

I appreciate your deep knowledge, but I am really not convinced that you are right this time.

As I mentioned before, I believe that you must *_NOT_* bind the socket to a specific interface IP; rather you bind it to IN_ADDR_ANY and then call IP_ADD_MEMBERSHIP on the socket explicitly for each specific physical NIC IP. (A side benefit of this is that you only need one socket to explicitly listen for multicasts on several NICs).

My code is listed below. And this seems now to work fine...

{code} { TUdpSocket }
function TUdpSocket.Bind(const AHost: string; APort: Word): boolean; var   Lrec: TSockAddr; begin   FillChar(Lrec, SizeOf(Lrec), #0);   Lrec.sin_family := AF_INET;   Lrec.sin_port := htons(APort);   Lrec.sin_addr.S_addr := AddrHostToNet(AHost);   Result := SocketOk and     (IdWinsock2.Bind(FSocket, @Lrec, sizeof(Lrec)) <> SOCKET_ERROR); end;
function TUdpSocket.Connect: boolean; begin   FSocket := Socket(AF_INET, SOCK_DGRAM, 0);   Result := SocketOk; end;
constructor TUdpSocket.Create; begin   inherited;   FSocket := INVALID_SOCKET; end;
procedure TUdpSocket.SetActive(const Value: boolean); begin   if Value <> Active then   begin     if Value then     begin       if not Connect then       begin         FSocket := INVALID_SOCKET;
raise Exception.CreateFmt('SetConnected() Error "%u"', [WSAGetLastError]);
      end;
    end
    else Disconnect;
  end;
end;

function TUdpSocket.SetReuseAddr(AValue: boolean): boolean; var   LoptVal: Integer; begin   LoptVal := Ord(AValue);   Result := SocketOk and
Success(SetSockOpt(FSocket, SOL_SOCKET, SO_REUSEADDR, @LoptVal, sizeof(LoptVal)));
end;

function TUdpSocket.JoinMulticastGroup(const AHost: string; const AInterface: string): boolean;
var
  LoptVal: ip_mreq;
begin
  FillChar(LoptVal, SizeOf(LoptVal), #0);
  LoptVal.imr_multiaddr.S_addr := AddrHostToNet(AHost);
  LoptVal.imr_interface.S_addr := AddrHostToNet(AInterface);
  Result := SocketOk and
Success(SetSockOpt(FSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, @LoptVal, sizeof(LoptVal)));
end;

function TUdpSocket.SocketOk: boolean; begin   Result := FSocket <> INVALID_SOCKET; end;
function TUdpSocket.Success(AResult: Integer): boolean; begin   Result := AResult <> SOCKET_ERROR; end;
{ TMulticastListener }
function TMulticastListener.Connect: boolean; var   i: Integer;   LInterfaces: TStringList; begin   Result := inherited             and SetReuseAddr(True)             and Bind('', FMulticastPort);   if Result then   begin     LInterfaces := TStringList.Create;     try       GStack.AddLocalAddressesToList(LInterfaces);       for i := 0 to LInterfaces.Count - 1 do
Result := Result and JoinMulticastGroup(FMulticastGroup, LInterfaces[i]);
    finally
      LInterfaces.Free;
    end;
  end;
  if Result then
  begin
    FThread := TMulticastListenerThread.Create(self);
    FThread.Start;
  end;
end; 

constructor TMulticastListener.Create; begin   inherited;   FMulticastGroup := '239.255.255.250';   FMulticastPort := 1900; end; {code}
-- Regards, AndrewFG
FYI: Phrase searches are enclosed in either single or double quotes
 
 
Originally created by
Tamarack Associates
Thu, 28 Mar 2024 09:54:55 UTC
Copyright © 2009-2024
HREF Tools Corp.