program broadcast_example;
{$mode objfpc}{$H+}
{$Assertions on}
uses
cthreads, SysUtils, Classes, Sockets;
procedure Broadcaster;
var
Sock: Tsocket;
Addr: TInetSockAddr;
Msg: String = 'Hello Broadcast';
OptVal, SetOptResult: Integer;
SendLen: SizeInt;
begin
// Wait for receiver to be setup
Sleep(1000);
Sock := fpsocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
Assert(Sock > 0, 'Error Creating Socket');
OptVal := 1;
SetOptResult := fpsetsockopt(Sock, SOL_SOCKET, SO_BROADCAST, @OptVal, SizeOf(OptVal));
Assert(SetOptResult = 0, 'Error Setting Broadcast');
WriteLn('Sending BroadCast: "', Msg, '"');
// Send Broadcast
Addr.sin_family := AF_INET; // IPv4 Addr
Addr.sin_addr := StrToNetAddr('127.255.255.255'); // Broadcast addr
Addr.sin_port := htons(1337); // Port
SendLen := fpsendto(Sock, @Msg[1], Msg.Length, 0, @Addr, SizeOf(Addr));
Assert(SendLen = Msg.Length, 'Error Sending Message');
end;
procedure Receiver;
var
Sock: Tsocket;
ListenAddr: TInetSockAddr;
Msg: String;
SenderAddrLen: tsocklen;
SenderAddr: TInetSockAddr;
MessageLen: SizeInt;
begin
Sock := fpsocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
Assert(Sock > 0, 'Error Creating Socket');
ListenAddr.sin_family := AF_INET; // IPv4 Addr
ListenAddr.sin_addr := StrToNetAddr('0.0.0.0'); // Receive over any NIC
ListenAddr.sin_port := htons(1337); // Listening Port
fpbind(Sock, @ListenAddr, SizeOf(ListenAddr));
SetLength(Msg, 512); // Max UDP Datagram length
SenderAddrLen := SizeOf(SenderAddr);
MessageLen := fprecvfrom(Sock, @Msg[1], Length(Msg), 0, @SenderAddr, @SenderAddrLen);
SetLength(Msg, MessageLen);
WriteLn('Received Message [', HostAddrToStr(SenderAddr.sin_addr), ':',
NToHs(SenderAddr.sin_port), ']: ', Msg);
end;
var
BCThread: TThread;
RCThread: TThread;
begin
// As I don't have two PCs at hand, I will simply use two threads and the loopback address
BCThread := TThread.CreateAnonymousThread(@Broadcaster);
RCThread := TThread.CreateAnonymousThread(@Receiver);
BCThread.FreeOnTerminate := False;
RCThread.FreeOnTerminate := False;
BCThread.Start;
RCThread.Start;
BCThread.WaitFor;
BCThread.Free;
RCThread.WaitFor;
RCThread.Free;
end.