Multicasting on Windows lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- ken_ramsey · 2019-08-21 03:07 Hello, I was having difficulty getting multicasting to work in Windows. I found out that somewhere along the line Microsoft changed the values of the constants used with the IPPROTO_IP flag when you use the setsockopt function. The Winsock packages for FPC have the value for IP_ADD_MEMBERSHIP set to 5, but in my version of the Windows SDK at least, this value is now 12. So the following sort of snippet fixes it: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   {$ifdef MSWINDOWS}  err := fpsetsockopt(sock, IPPROTO_IP, 12, @group, SizeOf(group));  {$else}  err := fpsetsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,         @group, SizeOf(group));  {$endif}  For completeness, here's a complete working example of a simple multicast listener of text-based traffic: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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. ---------------------------------------------------------------------- julkas · 2019-08-21 10:09 Quote from: ken_ramsey on August 21, 2019, 05:07:06 amHello, I was having difficulty getting multicasting to work in Windows. I found out that somewhere along the line Microsoft changed the values of the constants used with the IPPROTO_IP flag when you use the setsockopt function. The Winsock packages for FPC have the value for IP_ADD_MEMBERSHIP set to 5, but in my version of the Windows SDK at least, this value is now 12. Multicasting is great. I have cloned disk images (~200) with CloneZilla server / Fog. Please provide your FPC/Lazarus/OS version. ---------------------------------------------------------------------- ken_ramsey · 2019-08-21 14:15 Right, I should have included that, my bad: FPC Version: 3.0.4 [2017/10/06] Lazarus: 1.8.4 Windows Version: Windows 10 Pro Windows SDK: 10.0.17763.0 ---------------------------------------------------------------------- Remy Lebeau · 2019-08-21 22:26 Quote from: ken_ramsey on August 21, 2019, 05:07:06 amI found out that somewhere along the line Microsoft changed the values of the constants used with the IPPROTO_IP flag when you use the setsockopt function. The Winsock packages for FPC have the value for IP_ADD_MEMBERSHIP set to 5, but in my version of the Windows SDK at least, this value is now 12. Known issue with the Winsock SDK: INFO: Header and Library Requirement When Set/Get Socket Options at the IPPROTO_IP Level For comparison, Indy dynamically loads WS2.DLL on Windows CE and WS2_32.DLL on non-CE, so it uses the older values for Windows CE and the newer values for non-CE. ---------------------------------------------------------------------- julkas · 2019-08-22 08:24 Using Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i err := fpsetsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, @group, SizeOf(group));returns error - fpsetsockopt failed with 10042 on my FPC 3.0.4 / Lazarus 2.0.0 / Win 8. As described in link above. ---------------------------------------------------------------------- julkas · 2019-08-22 12:17 I have created simple project with Indy 10 IdIPMCastServer and tested it with your multicast listener on same PC. It works. P.S. My first impression about Indy 10 - good software. Check multicast server and client. ---------------------------------------------------------------------- Remy Lebeau · 2019-08-23 20:12 Quote from: julkas on August 22, 2019, 10:24:57 amUsing Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i err := fpsetsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, @group, SizeOf(group));returns error - fpsetsockopt failed with 10042 on my FPC 3.0.4 / Lazarus 2.0.0 / Win 8. As described in link above. 10042 is WSAENOPROTOOPT, which would be consistent with IP_ADD_MEMBERSHIP using the wrong numeric value for the version of Winsock you are accessing, as described in the MSDN article I linked to in my previous reply. Quote from: julkas on August 22, 2019, 02:17:42 pmI have created simple project with Indy 10 IdIPMCastServer and tested it with your multicast listener on same PC. It works. That is because Indy does not rely on FPC's socket constants, Indy defines its own constants. ---------------------------------------------------------------------- ken_ramsey · 2019-08-25 05:51 Quote from: julkas on August 22, 2019, 02:17:42 pmI have created simple project with Indy 10 IdIPMCastServer and tested it with your multicast listener on same PC. It works. P.S. My first impression about Indy 10 - good software. Check multicast server and client. Yes, you are correct, Indy is good software. It is, however, focused on TCP based applications. And that is quite understandable, that is where the lions' share of interest lies. Indy is not so good with UDP multicast. I don't blame them. My particular sphere of interest does heavily involve multicast UDP, including Zeroconf and mDNS and also much more in the UDP realm. I've run into a multitude of problems getting Indy to work in these domains. Again, I'm not surprised, I know that I'm working in an area that isn't interesting to most. One of my challenges is Zeroconf and mDNS, that heavily weds me to UDP multicasting solutions. But that's not all, I'm also involved in GigE Vision which also heavily weds me to UDP multicasting solutions. For the Zeroconf and mDNS, most people use Bonjour. But many others cannot because of licensing restrictions. Zeroconf is a wonderful thing. If I succeed in making a good Pascal solution, I'll share it. ---------------------------------------------------------------------- julkas · 2019-08-25 08:29 Quote from: ken_ramsey on August 25, 2019, 07:51:25 amI've run into a multitude of problems getting Indy to work in these domains. Can you give more info about? Quote from: ken_ramsey on August 25, 2019, 07:51:25 amOne of my challenges is Zeroconf and mDNS, that heavily weds me to UDP multicasting solutions. But that's not all, I'm also involved in GigE Vision which also heavily weds me to UDP multicasting solutions. For the Zeroconf and mDNS, most people use Bonjour. But many others cannot because of licensing restrictions. Zeroconf is a wonderful thing. If I succeed in making a good Pascal solution, I'll share it. Very interesting projects. Regards. ---------------------------------------------------------------------- Remy Lebeau · 2019-08-27 17:42 Quote from: julkas on August 25, 2019, 10:29:54 amQuote from: ken_ramsey on August 25, 2019, 07:51:25 amI've run into a multitude of problems getting Indy to work in these domains. Can you give more info about? Yes, please.  I can't help you if you don't explain what is actually wrong.  Also, Indy does have an issue tracker you can submit problems to.