Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do Network discovery using UDP broadcast

Tags:

c#

udp

I want to to do network discovery using UDP Broadcast in C#. I don't know how to do this. Can you give me advice on how to do it?

I want to do like this tutorial.

like image 889
NTK88 Avatar asked Apr 04 '14 03:04

NTK88


People also ask

How do I broadcast using UDP?

Connecting via UDPSet the IP address of the PC's Network card to the same subnet than your Audia/Nexia units. In Audia/Nexia/DaVinci software, go to the Tools menu > Options > Network tab. In the Network Device Discovery Method section, make sure UDP Broadcast is selected.

What is a UDP broadcast address?

The UDP broadcast address represents the entire subnet where a host is located, and you can determine this address using the appropriate operating system commands from any host on the subnet.

Can TCP be used for broadcast?

The TCP/IP can send data to all hosts on a local network or to all hosts on all directly connected networks. Such transmissions are called broadcast messages. For example, the routed routing daemon uses broadcast messages to query and respond to routing queries.


2 Answers

It's very simple to make same thing in C#

Server:

var Server = new UdpClient(8888); var ResponseData = Encoding.ASCII.GetBytes("SomeResponseData");  while (true) {     var ClientEp = new IPEndPoint(IPAddress.Any, 0);     var ClientRequestData = Server.Receive(ref ClientEp);     var ClientRequest = Encoding.ASCII.GetString(ClientRequestData);      Console.WriteLine("Recived {0} from {1}, sending response", ClientRequest, ClientEp.Address.ToString());     Server.Send(ResponseData, ResponseData.Length, ClientEp); } 

Client:

var Client = new UdpClient(); var RequestData = Encoding.ASCII.GetBytes("SomeRequestData"); var ServerEp = new IPEndPoint(IPAddress.Any, 0);  Client.EnableBroadcast = true; Client.Send(RequestData, RequestData.Length, new IPEndPoint(IPAddress.Broadcast, 8888));  var ServerResponseData = Client.Receive(ref ServerEp); var ServerResponse = Encoding.ASCII.GetString(ServerResponseData); Console.WriteLine("Recived {0} from {1}", ServerResponse, ServerEp.Address.ToString());  Client.Close(); 
like image 180
rufanov Avatar answered Sep 30 '22 01:09

rufanov


Here is a different solution that is serverless. I had a need to have a bunch of raspberry pis be aware of each other on a network, but had no guarantees of who would be active. So this approach allows everyone to be a client! The complete library is available on GitHub (disclaimer: I created) and that makes this whole process really reaaaally easy for UWP apps.

https://github.com/mattwood2855/WindowsIotDiscovery

This solution assumes that device names are unique and that you want to use JSON strings as the communication protocol, but you could easily just send any other format. Also, in practice try-catch everything ;)

The general mechanism:

Discover your IpAdress

public string IpAddress {     get     {         var hosts = NetworkInformation.GetHostNames();         foreach (var host in hosts)         {             if (host.Type == HostNameType.Ipv4) return host.DisplayName;             }         return "";     } } 

Set up your listener

var udpPort = "1234"; var socket = new DatagramSocket(); socket.MessageReceived += ReceivedDiscoveryMessage; await socket.BindServiceNameAsync(udpPort);` 

Handle incoming data

async void ReceivedDiscoveryMessage(DatagramSocket socket, DatagramSocketMessageReceivedEventArgs args) {     // Get the data from the packet     var result = args.GetDataStream();     var resultStream = result.AsStreamForRead();     using (var reader = new StreamReader(resultStream))     {         // Load the raw data into a response object         var potentialRequestString = await reader.ReadToEndAsync();          // Ignore messages from yourself         if (args.RemoteAddress.DisplayName == IpAddress) return;                 // Get the message         JObject jRequest = JObject.Parse(potentialRequestString);         // Do stuff with the data     } } 

Send a message

public async void SendDataMessage(string discoveryMessage) {     // Get an output stream to all IPs on the given port     using (var stream = await socket.GetOutputStreamAsync(new HostName("255.255.255.255"), udpPort))     {         // Get a data writing stream         using (var writer = new DataWriter(stream))         {             // Write the string to the stream             writer.WriteString(discoveryMessage);             // Commit             await writer.StoreAsync();         }     } } 

The idea would be to send a discovery message containing your ip address and name. Then in the receive message function add the ip-name pairs to a List of devices. Add a little logic to avoid duplicates and update Ip address if the ip changes for a given name.

As a bonus, you can have each device send the list of devices they know about. This allows you to minimize udp traffic by not responding when the sender is aware of you. You can even have the receiver compare the list against their own list to discover other devices.

Redundancy is your friend with UDP, there is no guarantee that a packet will be delivered.

like image 43
Mr Wood Avatar answered Sep 30 '22 03:09

Mr Wood