While the implementation is mostly transparent, there are some important and subtle differences that must be taken into consideration:
udp_subnet 
scope is not reentrant. If a listener performs a broadcast_request/1 
with UDP scope recursively, then disaster looms certain. This caveat 
does not apply to a UDP scoped broadcast/1, 
which can safely be performed from a listener context.ip(A,B,C,D) 
or an atom or string of the format A.B.C.D. Options 
processed:
subnet.For compatibility reasons Options may be the subnet mask.
| Address | has canonical form ip(A,B,C,D):Port. | 
%prolog\n, followed by the Prolog term in quoted notation 
while ignoring operators. This hook may use alternative serialization 
such as fast_term_serialized/2, use library(ssl) 
to realise encrypted messages, etc.
| Scope | is the scope for which the message is broadcasted. This can be used to use different serialization for different scopes. | 
| Term | encapsulates the term broadcasted by 
the application as follows: 
 
 | 
udp(invalid_message) to stop processing 
the message.
This hook is intended to initiate a new node joining the network of 
peers. We could in theory also omit the in-scope test and use a normal 
broadcast to join. Using a different channal however provides a basic 
level of security. A possibe implementation is below. The first fragment 
is a hook added to the server, the second is a predicate added to a 
client and the last initiates the request in the client. The excanged 
term (join(X)) can be used to exchange a welcome handshake.
:- multifile udp_broadcast:udp_unicast_join_hook/3.
udp_broadcast:udp_unicast_join_hook(Scope, From, join(welcome)) :-
    udp_peer_add(Scope, From),
join_request(Scope, Address, Reply) :-
    udp_peer_add(Scope, Address),
    broadcast_request(udp(Scope, join(X))).
?- join_request(myscope, "1.2.3.4":10001, Reply). Reply = welcome.