program MulticastListener;
uses
Sockets, SysUtils;
type
TImReq = packed record
imr_multicast: TInAddr;
imr_interface: TInAddr;
end;
var
sock: TSocket;
iface: TInetSockAddr;
mcaststr: String;
nicstr: String;
portno: Word;
argno: Integer;
err: Integer;
opt: Integer;
group: TImReq;
buflen: LongInt;
buf: Array[1..4096] of Byte;
msg: AnsiString;
nbytes: ssize_t;
sender: TInetSockAddr;
procedure Usage;
begin
WriteLn('Usage: MulticastListener -i iface -m mcastaddr -p portno');
WriteLn;
Halt;
end;
begin
argno := 1;
nicstr := '';
mcaststr := '';
portno := 0;
while argno <= ParamCount do
begin
if ParamStr(argno) = '-i' then
begin
Inc(argno);
nicstr := ParamStr(argno);
end
else if ParamStr(argno) = '-m' then
begin
Inc(argno);
mcaststr := ParamStr(argno);
end
else if ParamStr(argno) = '-p' then
begin
Inc(argno);
portno := StrToInt(ParamStr(argno));
end
else
Usage;
Inc(argno);
end;
if (portno = 0) or (nicstr = '') or (mcaststr = '') then
Usage;
sock := fpsocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if sock = SOCKET_ERROR then
begin
WriteLn('fpsocket failed with ', socketerror);
Halt;
end;
with iface do
begin
sin_family:=AF_INET;
sin_addr := StrToNetAddr(nicstr);
sin_port := htons(portno);
end;
err := fpbind(sock, PSockAddr(@iface), SizeOf(iface));
if err <> 0 then
begin
WriteLn('fpbind failed with ', socketerror);
Halt;
end;
opt := 1;
err := fpsetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, @opt, SizeOf(opt));
if err <> 0 then
begin
WriteLn('fpsetsockopt failed with ', socketerror);
Halt;
end;
group.imr_interface.s_addr:=StrToNetAddr(nicstr).s_addr;
group.imr_multicast.s_addr:=StrToNetAddr(mcaststr).s_addr;
{$ifdef MSWINDOWS}
err := fpsetsockopt(sock, IPPROTO_IP, 12, @group, SizeOf(group));
{$else}
err := fpsetsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
@group, SizeOf(group));
{$endif}
if err <> 0 then
begin
WriteLn('fpsetsockopt failed with ', socketerror);
Halt;
end;
while True do
begin
buflen := SizeOf(sender);
nbytes := fprecvfrom(sock, @buf, 4096, 0, @sender, @buflen);
if nbytes < 0 then
begin
WriteLn('fprecvfrom failed with ', socketerror);
Halt;
end;
SetString(msg, PAnsiChar(@buf[1]), nbytes);
WriteLn(Format('[%s@%d]: %s', [NetAddrToStr(sender.sin_addr),
ntohs(sender.sin_port),
msg]));
end;
end.