Broadcasting:
Occurs when a host sends a datagram to all other hosts on the network.
It is actually quite simple, just send packets to the specially designated broadcast address "255.255.255.255".
All hosts listening on the wire, will receive the same datagram, and it is limited to the local network only.
The main advantage is that the listeners do not need to know the server address, all they have to do is to wait for the incoming packets.
Example on how i am using it with a local WiFi (mixing Windows PC and Android tablets):
When playing audio live, the band leader uses it to trigger a new datagram (with lyric text) when moving from one section to another, to display the current vocal to sing altogether with the chord notations.
Another typical use, is to help musicians to be in sync: "1", "2", "3", "4", "start playing", or to use it as an extra "click track" (metronome).
The Sender'// Sender
'// Broadcast datagram to multiple recipients
'// Author Patrice Terrier
'// www.zapsolution.com
'// Date: 10-06-2015
#BREAK ON
#COMPILE EXE "Sender.exe"
#Include "win32api.inc"
#Include "time.inc"
%PORT_NUMBER = 8000
$DEST_ADDR = "255.255.255.255"
%BUFFER_SIZE = 4096
%DELAY = 1000
function pbmain() as long
local lps as DWORD '// Socket descriptor of server
local nDoIt, broadcast, current_time as long
local sendaddr as sockaddr_in
local recvaddr as sockaddr_in
local wsa as WSADATA '// Used to open windows connection
'// Open windows connection
if (WSAStartup(&h0202, wsa)) then
print "Could not open Windows connection."
function = 0: exit function
end if
nDoIt = -1
lps = socket(%AF_INET, %SOCK_DGRAM, byval %NULL)
if (lps = %INVALID_SOCKET) then
print "Could not create socket."
lps = 0
nDoIt = 0
else
broadcast = 1
if (setsockopt(lps, %SOL_SOCKET, %SO_BROADCAST, broadcast, sizeof(long)) = -1) then
print "Could not set socket option"
nDoIt = 0
end if
end if
if (nDoIt) then
RtlFillMemory(byval varptr(sendaddr), sizeof(sockaddr_in), 0)
sendaddr.sin_family = %AF_INET
sendaddr.sin_port = htons(%PORT_NUMBER)
sendaddr.sin_addr.s_addr = %INADDR_ANY
if (bind(lps, sendaddr, sizeof(sockaddr_in)) = -1) then
print "Could not bind name to socket."
else
print "Press the Escape key to STOP everything"
RtlFillMemory(byval varptr(recvaddr), sizeof(sockaddr_in), 0)
recvaddr.sin_family = %AF_INET
recvaddr.sin_port = htons(%PORT_NUMBER)
recvaddr.sin_addr.s_addr = inet_addr($DEST_ADDR)
local zBuffer as asciiz * %BUFFER_SIZE
local nSTOP as long
local nTick as dword
nTick = GetTickCount() + %DELAY
do
RtlFillMemory(byval varptr(zBuffer), sizeof(zBuffer), 0)
if (asc(inkey$) = 27) then
zBuffer = "STOP"
nSTOP = 27
else
if (GetTickCount() > nTick) then
nTick = GetTickCount() + %DELAY
zBuffer = Time$
end if
end if
if (len(zBuffer)) then
print zBuffer
if (sendto(lps, zBuffer, sizeof(zBuffer), 0, recvaddr, sizeof(sockaddr_in)) <> sizeof(zBuffer)) then
print "Error sending datagram.": exit do
end if
end if
loop until nSTOP = 27
end if
end if
if (lps) then closesocket(lps)
WSACleanup()
function = 0
end function
The Receiver'// Receiver
'// Broadcast datagram to multiple recipients
'// Author Patrice Terrier
'// www.zapsolution.com
'// Date: 10-06-2015
#BREAK ON
#COMPILE EXE "Receiver.exe"
#Include "win32api.inc"
#Include "time.inc"
%PORT_NUMBER = 8000
$DEST_ADDR = "255.255.255.255"
%BUFFER_SIZE = 4096
function pbmain() as long
local lps as DWORD '// Socket descriptor of server
local nDoIt, broadcast, current_time as long
local sendaddr as sockaddr_in
local recvaddr as sockaddr_in
local addr_len as long
local wsa as WSADATA '// Used to open windows connection
'// Open windows connection
if (WSAStartup(&h0202, wsa)) then
print "Could not open Windows connection."
function = 0: exit function
end if
nDoIt = -1
lps = socket(%AF_INET, %SOCK_DGRAM, byval %NULL)
if (lps = %INVALID_SOCKET) then
print "Could not create socket."
lps = 0
nDoIt = 0
else
broadcast = 1
if (setsockopt(lps, %SOL_SOCKET, %SO_BROADCAST, broadcast, sizeof(long)) = -1) then
print "Could not set socket option"
nDoIt = 0
end if
end if
if (nDoIt) then
RtlFillMemory(byval varptr(recvaddr), sizeof(sockaddr_in), 0)
recvaddr.sin_family = %AF_INET
recvaddr.sin_port = htons(%PORT_NUMBER)
recvaddr.sin_addr.s_addr = %INADDR_ANY
if (bind(lps, recvaddr, sizeof(sockaddr_in)) = -1) then
print "Could not bind name to socket."
else
print "Press Escape to quit"
RtlFillMemory(byval varptr(sendaddr), sizeof(sockaddr_in), 0)
sendaddr.sin_family = %AF_INET
sendaddr.sin_port = htons(%PORT_NUMBER)
sendaddr.sin_addr.s_addr = %INADDR_ANY
local zBuffer as asciiz * %BUFFER_SIZE
addr_len = sizeof(sendaddr)
do
if (recvfrom(lps, zBuffer, sizeof(zBuffer), 0, sendaddr, addr_len) < 0) then
print "Error receiving data."
else
'// Display server message
print "Server message is: " + zBuffer
if (zBuffer = "STOP") then exit do
end if
loop until asc(inkey$) = 27
end if
end if
if (lps) then closesocket(lps)
WSACleanup()
function = 0
end function
The attached zip file comprise the source code and the compiled PBCC exe (console application).
Here is the translation into 32-bit C++ source code.
Sender
// Sender
// Broadcast datagram to multiple recipients
// Author Patrice Terrier
// www.zapsolution.com
// Date: 10-07-2015
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock.h>
#define PORT_NUMBER 8000
#define BUFFER_SIZE 4096
#define DELAY 1000
const char* DEST_ADDR = "255.255.255.255";
int __cdecl main() {
WSADATA wsa; // Used to open windows connection
int nDoIt = 1, broadcast = 1, nStop = 0;
DWORD nTick = 0;
int nLen = sizeof(int);
SOCKET lps; // Socket descriptor of server
struct sockaddr_in sendaddr; // Information about the server
struct sockaddr_in recvaddr; // Information about the client
char zBuffer[BUFFER_SIZE]; // Where to store received data
time_t current_time; // Current time
char zTime[26] = { 0 };
// Open windows connection
if (WSAStartup(0x0202, &wsa)) {
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}
// Open a datagram socket
lps = socket(AF_INET, SOCK_DGRAM, 0);
if (lps == INVALID_SOCKET) {
fprintf(stderr, "Could not create socket.\n");
lps = 0;
nDoIt = 0;
} else {
if (setsockopt(lps, SOL_SOCKET, SO_BROADCAST, (char*) &broadcast, nLen) == -1) {
fprintf(stderr, "Could not set socket option.\n");
nDoIt = 0;
}
}
if (nDoIt) {
RtlFillMemory((void*) &sendaddr, sizeof(sendaddr), '\0');
sendaddr.sin_family = AF_INET;
sendaddr.sin_port = htons(PORT_NUMBER);
sendaddr.sin_addr.s_addr = INADDR_ANY;
if (bind(lps, (struct sockaddr*) &sendaddr, sizeof(struct sockaddr_in)) == -1) {
fprintf(stderr, "Could not bind to socket.\n");
} else {
fprintf(stderr, "Press the Escape key to STOP everything.\n");
RtlFillMemory((void*)&recvaddr, sizeof(recvaddr), '\0');
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(PORT_NUMBER);
recvaddr.sin_addr.s_addr = inet_addr(DEST_ADDR);
nTick = GetTickCount() + DELAY;
do {
RtlFillMemory((void*) &zBuffer, sizeof(zBuffer), '\0');
if (GetAsyncKeyState(VK_ESCAPE)) {
strcpy_s(zBuffer, sizeof(zBuffer), "STOP");
nStop = 27;
} else {
if (GetTickCount() > nTick) {
nTick = GetTickCount() + DELAY;
current_time = time(NULL);
ctime_s(zTime, sizeof(zTime), ¤t_time);
strcpy_s(zBuffer, sizeof(zBuffer), zTime);
}
}
if (strlen(zBuffer)) {
fprintf(stderr, zBuffer);
if (sendto(lps, zBuffer, sizeof(zBuffer), 0, (struct sockaddr*) &recvaddr, sizeof(recvaddr)) != sizeof(zBuffer)) {
fprintf(stderr, "Error sending datagram.\n");
break;
}
}
} while (nStop != 27);
}
}
if (lps) { closesocket(lps); }
WSACleanup();
return 0;
}
Receiver
// Receiver
// Broadcast datagram to multiple recipients
// Author Patrice Terrier
// www.zapsolution.com
// Date: 10-07-2015
#include <stdio.h>
#include <winsock.h>
#define PORT_NUMBER 8000
#define BUFFER_SIZE 4096
const char* DEST_ADDR = "255.255.255.255";
int __cdecl main() {
WSADATA wsa; // Used to open windows connection
int nDoIt = 1, broadcast = 1, nStop = 0;
DWORD nTick = 0;
int nLen = sizeof(int);
SOCKET lps; // Socket descriptor of server
struct sockaddr_in sendaddr; // Information about the server
struct sockaddr_in recvaddr; // Information about the client
char zBuffer[BUFFER_SIZE]; // Where to store received data
// Open windows connection
if (WSAStartup(0x0202, &wsa)) {
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}
// Open a datagram socket
lps = socket(AF_INET, SOCK_DGRAM, 0);
if (lps == INVALID_SOCKET) {
fprintf(stderr, "Could not create socket.\n");
lps = 0;
nDoIt = 0;
}
else {
if (setsockopt(lps, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast, nLen) == -1) {
fprintf(stderr, "Could not set socket option.\n");
nDoIt = 0;
}
}
if (nDoIt) {
RtlFillMemory((void*) &recvaddr, sizeof(recvaddr), '\0');
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(PORT_NUMBER);
recvaddr.sin_addr.s_addr = INADDR_ANY;
if (bind(lps, (struct sockaddr*) &recvaddr, sizeof(struct sockaddr_in)) == -1) {
fprintf(stderr, "Could not bind to socket.\n");
} else {
fprintf(stderr, "Press the Escape key to quit.\n");
RtlFillMemory((void*) &sendaddr, sizeof(sendaddr), '\0');
sendaddr.sin_family = AF_INET;
sendaddr.sin_port = htons(PORT_NUMBER);
sendaddr.sin_addr.s_addr = INADDR_ANY;
RtlFillMemory((void*)&zBuffer, sizeof(zBuffer), '\0');
nLen = sizeof(sendaddr);
do {
if (GetAsyncKeyState(VK_ESCAPE)) {
fprintf(stderr, "STOP\n");
nStop = 27;
} else {
if (recvfrom(lps, zBuffer, sizeof(zBuffer), 0, (struct sockaddr*) &sendaddr, &nLen) < 0) {
fprintf(stderr, "Error receiving datagram.\n");
} else {
fprintf(stderr, "Sender message is: ");
fprintf(stderr, zBuffer);
if (strcmp(zBuffer, "STOP") == 0) { nStop = 27; }
}
}
} while (nStop != 27);
}
}
if (lps) { closesocket(lps); }
WSACleanup();
return 0;
}
Patrice,
I thought you were coding only for 64 bit c++ ?
James
In that very specific case, datagrams are also sent to Android on the local network,
that means using 32-bit and Unicode.
...