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

Posted

技术标签:

【中文标题】客户端应用程序在 C# 中查找本地网络上的服务器的最佳方法是啥?【英文标题】:What is the best way for a client app to find a server on a local network in C#?客户端应用程序在 C# 中查找本地网络上的服务器的最佳方法是什么? 【发布时间】:2010-09-17 15:34:42 【问题描述】:

客户端使用 GenuineChannels 连接到服务器(我们正在考虑切换到 DotNetRemoting)。我所说的 find 是获取要连接的服务器的 IP 和端口号。

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

【问题讨论】:

re: 蛮力方法——这是可能的。你确实想要更好的方法。 :) 即使使用大规模并行、多套接字方法(概念上类似于 fping),测试 LAN 子网中的所有节点(和所有潜在端口)仍然需要几分钟时间。我在产品中的代码正是这样做的,因为该服务没有更好的选择。叹息。 【参考方案1】:

只是想指出一个替代的 Zeroconf NuGet 包:Zeroconf。它没有任何本机依赖项,​​因此您无需安装 Bonjour for Windows 或其他任何东西。

它支持 .NET 4.5、WP8 和 Win8。

【讨论】:

良好的网络礼仪应包括免责声明,即这是您自己的广告项目。不会标记它,因为它仍然相关,但需要考虑。 不知道为什么这很重要,因为它是一个免费、开源的解决方案,具有更好、更简单的技术实现。任何访问 Nuget 页面或 GitHub 项目站点的人都会看到是我;没有理由否认任何事情。这里没有“产品”或赚钱。 如果它也有服务器模式来验证就好了。这个“更好更简单的技术实现”在哪里? @ClaireNovotny 我正在使用您的 ZeroConf 库。不错的作品。我有两台设备正在发现他们宣传的服务。但是,一个以适当的数据结构返回 IP 地址,而另一个服务 IP 地址仅在“Id”字段中返回。有什么想法吗?【参考方案2】:

WS-Discovery 是用于此目的的协议。它有一些不同的变体、不同风格的广播和代理。 http://en.wikipedia.org/wiki/WS-Discovery

.NET WCF4 实现了这一点。

【讨论】:

WS-Discovery 非常适合发现“Web 服务”。这些通常服务于 SOAP 或 REST。不同的风格服务器可能更适合不同的风格发现。【参考方案3】:

我想说最好的方法是在 C# 中使用 Bonjour/Zeroconf/mDNS;为了让它与网络融为一体,我们花了很多心思; IE 如果可能,它会随着时间的推移减少 ping 的频率,等等。有 Mono.Zeroconf,我读到 Apple SDK 中有一个较旧的 .NET 项目,但我没有找到它。

所以最简单的方法是安装Bonjour for Windows,然后获取Windows Binaries for Mono.Zeroconf 尝试示例MZClient.exeMono.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");

【讨论】:

【参考方案4】:

考虑广播特定的 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
    

【讨论】:

【参考方案5】:

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

【讨论】:

虽然为“ping”和“reply”实现自己的 UDP 端口通道很容易、快速并且看起来很轻松,但如果您不通过标准,它会增加端口/使用的混乱发表过程(也是一种痛苦)。此外,已经有许多发现协议在大多数操作系统上实现。请记住:“优秀的程序员会写出优秀的代码。优秀的程序员会重用已有的优秀代码。”

以上是关于客户端应用程序在 C# 中查找本地网络上的服务器的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Android - 在网络中查找服务器

允许客户端应用程序自动连接到同一网络上的服务器应用程序

C# - 连接到 (RAS) *** 时如何获取 IP 地址

查找服务的标准方法(在本地网络中打开端口)

本地网络上的 Socket.io/node.js?

从 C# 中的 IP 获取本地网络上的机器 MAC 地址