客户端应用程序在C#中如何在本地网络上查找服务器的最佳方法?

15

客户端使用GenuineChannels连接服务器(我们正在考虑切换到DotNetRemoting)。通过“查找”,我的意思是获取要连接的服务器的IP和端口号。

暴力破解似乎是一种方法,可以尝试网络上的每个IP并尝试活动端口(甚至不确定是否可能),但必须有更好的方法。


关于暴力破解方法--这是可能的。但您确实希望有更好的方法。 :) 即使使用大规模并行、多插槽方法(在概念上类似于fping),测试LAN子网中的所有节点(和所有潜在端口)仍然需要几分钟时间。我有一款产品中就是用这种方法,因为没有更好的选择。叹息。 - Jesse Chisholm
5个回答

12

考虑广播特定的UDP数据包。当服务器看到广播的UDP数据包时,它们会发送回复。客户端可以从所有服务器收集回复,然后开始连接它们或者基于选举算法进行连接。

请参考以下客户端示例(未经测试的代码):


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
    }
}

10

我认为在C#中使用Bonjour/Zeroconf/mDNS是最好的方法;这方面考虑得非常周到,使它能够良好地与网络协作。例如,如果可能的话,它会随着时间的推移降低ping的频率等。有一个叫做Mono.Zeroconf的库,而且我看到在Apple SDK中还有一个旧的.NET项目,但我没有找到它。

所以最简单的方法是安装Bonjour for Windows,然后获取Windows Binaries for Mono.Zeroconf,尝试例子MZClient.exe,将Mono.Zeroconf.dll和/或Mono.Zeroconf.Providers.Bonjour.dll添加到您的项目引用中并运行。

像这样:

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");

5

我想提供一个替代Zeroconf NuGet软件包的方案:Zeroconf。它没有任何本地依赖,所以你不需要安装Bonjour for Windows或其他任何东西。

它支持.NET 4.5、WP8和Win8。


5
良好的网络礼仪应包括免责声明,说明这是你自己的项目宣传。我不会标记它,因为它仍然相关,但这是需要考虑的事情。 - nathanchere
2
不确定为什么这很重要,因为它是一个免费、开源的解决方案,具有更好和更简单的技术实现。任何前往Nuget页面或GitHub项目网站的人都会看到是我;没有理由否认任何东西。这里没有任何“产品”或金钱被赚取。 - Claire Novotny
它也有服务器模式进行验证会更好。这个“更好和更简单的技术实现”在哪里? - kchoi
@ClaireNovotny 我正在使用你的ZeroConf库,做得很好。我有两个设备,正在发现它们广告的服务。然而,一个设备返回了适当的数据结构中的IP地址,而另一个设备的IP地址只在“Id”字段中返回。有什么想法吗? - Chimera

3

1
WS-Discovery非常适合发现“Web服务”。这些服务通常提供SOAP或REST。不同风格的服务器可能更适合不同风格的发现。 - Jesse Chisholm

2

让服务器在网络上的特定端口监听广播(必须使用UDP)。当客户端启动时,在该端口上广播一些“ping”请求。当服务器看到“ping”时,它将发送一个消息,其中包含客户端连接所需的TCP地址和端口。


尽管为“ping”和“reply”实现自己的UDP端口通道很容易、快捷且似乎不会带来痛苦,但如果您不经过标准出版流程(也是一种痛苦),它会增加端口/使用混淆。此外,已经有许多发现协议及其在大多数操作系统上的实现。记住:“好的程序员编写好的代码。优秀的程序员重复使用现有的好代码。” - Jesse Chisholm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接