What is the best way for a client app to find a server on a local network in C#?
Asked Answered
B

5

15

The client connects to the server using GenuineChannels (we are considering switching to DotNetRemoting). What I mean by find is obtain the IP and port number of a server to connect to.

It seems like a brute-force approach would be try every IP on the network try the active ports (not even sure if that's possible) but there must be a better way.

Blau answered 16/10, 2008 at 21:55 Comment(1)
re: brute force approach -- It is possible. You do want a better way. :) Even using a massively parallel, multiple socket approach (conceptually similar to fping) it can still take several minutes to test all nodes (and all potential ports) in a LAN subnet. I have code in product that does exactly that because there was no better choice for that service. Sigh.Swath
M
12

Consider broadcasting a specific UDP packet. When the server or servers see the broadcasted UDP packet they send a reply. The client can collect the replies from all the servers and start connecting to them or based on an election algorithm.

See example for client (untested code):


using System.Net;
using System.Net.Sockets;

[STAThread]
static void Main(string[] args)
{
    Socket socket = new Socket(AddressFamily.InterNetwork,
    SocketType.Dgram, ProtocolType.Udp);
    socket.Bind(new IPEndPoint(IPAddress.Any, 8002));
    socket.Connect(new IPEndPoint(IPAddress.Broadcast, 8001));
    socket.Send(System.Text.ASCIIEncoding.ASCII.GetBytes("hello"));

    int availableBytes = socket.Available;
    if (availableBytes > 0)
    {
        byte[] buffer = new byte[availableBytes];
        socket.Receive(buffer, 0, availableBytes, SocketFlags.None);
        // buffer has the information on how to connect to the server
    }
}
Maund answered 16/10, 2008 at 22:2 Comment(0)
S
11

I'd say the best way is to use Bonjour/Zeroconf/mDNS for C#; a lot of thought went into making it play nice with the network; IE it pings less frequently over time if possible, etc. There's Mono.Zeroconf, and I read there's an older .NET project in the Apple SDK but I haven't found it.

So the easiest would be to install Bonjour for Windows, then get the Windows Binaries for Mono.Zeroconf try the example MZClient.exe drop the Mono.Zeroconf.dll and/or Mono.Zeroconf.Providers.Bonjour.dll into your project references and go.

Something like this:

var service = new Mono.Zeroconf.RegisterService {
                Name = "Use Me for Stuff",
                RegType = "_daap._tcp",
                ReplyDomain = "local.",
                Port = 0024200,
                TxtRecord = new Mono.Zeroconf.TxtRecord {
                            {"I have no idea what's going on", "true"}}
              };
service.Register();

var browser = new Mono.Zeroconf.ServiceBrowser();
browser.ServiceAdded +=
    delegate(object o, Mono.Zeroconf.ServiceBrowseEventArgs args) {
        Console.WriteLine("Found Service: {0}", args.Service.Name);
        args.Service.Resolved +=
            delegate(object o, Mono.Zeroconf.ServiceBrowseEventArgs args) {
                var s = args.Service;
                Console.WriteLine(
                    "Resolved Service: {0} - {1}:{2} ({3} TXT record entries)",
                    s.FullName, s.HostEntry.AddressList[0], s.Port, s.TxtRecord.Count);
          };
        args.Service.Resolve();
    };
browser.Browse("_daap._tcp", "local");
Shafting answered 16/10, 2008 at 22:27 Comment(0)
P
5

Just wanted to point out an alternative Zeroconf NuGet package: Zeroconf. It does not have any native dependencies, so you don't need to install Bonjour for Windows or anything else.

It has support for .NET 4.5, WP8 and Win8.

Pryce answered 19/9, 2013 at 13:34 Comment(4)
Good netiquette would include a disclaimer that this is your own project you're advertising. Not going to flag it because it's still relevant, but something to consider.Proxy
Not sure why this matters as it's a free, open source, solution to the issue that has a better and simpler technical implementation. Anyone going to the Nuget page or the GitHub project site would see it's me; there's no reason to disclaim anything. There's no "product" or money being made here.Pryce
Would be nice if it had server mode too for verifying. Where is this "better and simpler technical implementation"?Colville
@ClaireNovotny I'm using your ZeroConf library. Nice work. I have two devices that I'm discovering the services they advertise. However, one returns the IP address in the appropriate data structure while the other service IP address is only returned in the "Id" field. Any ideas?Segal
C
3

WS-Discovery is a protocol intended for this purpose. It has a few different variations, different flavors of broadcasting and proxies. http://en.wikipedia.org/wiki/WS-Discovery

.NET WCF4 implements this.

Cuirbouilli answered 3/3, 2011 at 11:9 Comment(1)
WS-Discovery lends itself well to discovering "Web Services". These typically serve SOAP or REST. A different style server may better fit a different style discovery.Swath
I
1

Have the server listen for broadcast on a specific port on the network (must use UDP), When client starts have it broadcast some "ping" request on that port. when the server sees a "ping" it send back a message with the TCP address and port required for the client to connect to it.

Insistent answered 16/10, 2008 at 22:1 Comment(1)
While implementing your own UDP port channel for a "ping" and "reply" is easy, quick, and seems painless, it adds to the port/use confusion if you don't go through the standards publication process (also a pain). Also, there are already many discovery protocols out there with implementations on most OSes. Remember: "A good programmer writes good code. A great programmer re-uses preexisting good code."Swath

© 2022 - 2024 — McMap. All rights reserved.