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

Allow client app to automatically connect to server app on same network

我创建了两个应用程序(一个客户端和一个服务器),只要我输入机器的本地 IP 地址,服务器应用程序就可以相互通信 运行正在连接到客户端应用程序(在代码中)。

我希望客户端应用程序自动发现 运行 机器的本地 IP 地址并连接到服务器应用程序,这样它们就可以 运行 在任何网络上而不需要在代码中输入IP。

这两个应用 运行 在同一个网络上(即通过 WiFi,而不是互联网)

这是我目前在我的客户端应用程序中的内容:

// COMMUNICATE WITH SERVER

    private TcpClient client = new TcpClient();
    private IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("192.168.2.35"), 8888);

    public Console()
    {
        InitializeComponent();
        client.Connect(serverEndPoint);
    }

    private void SendMessage(string msg)
    {
        NetworkStream clientStream = client.GetStream();

        ASCIIEncoding encoder = new ASCIIEncoding();
        byte[] buffer = encoder.GetBytes(msg);

        clientStream.Write(buffer, 0, buffer.Length);
        clientStream.Flush();
    }

在此示例中,我只能连接到“192.168.2.35”上的服务器 运行ning,我希望它能够在任何端口 8888 上找到服务器 运行ning网络上的机器。

或者,如果这不可能,我希望服务器将其 IP 作为消息(某种)广播,并让客户端接收此消息并验证它是服务器并连接到它。

我认为我的第二个示例是执行此操作的正确方法,但我似乎无法全神贯注于如何让它工作(我对 C# 还很陌生),以及我的任何其他示例我发现我似乎无法使用我的应用程序。

这是我的服务器代码,如果它有助于回答我的问题:

private void Server()
    {
        this.tcpListener = new TcpListener(IPAddress.Any, 8888);
        this.listenThread = new Thread(new ThreadStart(ListenForClients));
        this.listenThread.Start();
    }

    private void ListenForClients()
    {
        this.tcpListener.Start();

        while (true)
        {
            TcpClient client = this.tcpListener.AcceptTcpClient();


            connectedClients++;
            lblNumberOfConnections.Text = connectedClients.ToString();

            Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
            clientThread.Start(client);

        }

谢谢



编辑: 我已经尝试将 THIS 添加到我的项目中,但是太新了我不确定如何正确地实现它,但它没有带我去任何地方。


第二次编辑: 我已经尝试实施 UDP 广播几次,但还没有成功。我最近的尝试是实现 THIS(减去聊天部分)。我似乎根本无法在我的项目中使用 UDP 广播,因为以我目前的技能水平,这似乎超出了我的理解范围。不幸的是,让我的客户端自动连接到服务器是我的项目正常运行所必需的 100%...

我的另一个问题可能最好单独提出一个问题,但与此问题有些相关的是:我的客户端 GUI 由一个面板组成,该面板在多个自定义 class 之间切换,每个包含不同的与我尝试连接的服务器通信的按钮等(类似于标签页)。一旦我弄清楚了 UDP 广播,我是否需要将其分别编码到每个 class 中?或者有没有办法让我的面板中的所有 classes 运行ning 连接到同一台服务器?

一个简单但可能成本高昂(就网络流量而言)的解决方案是让您的服务器应用程序通过 UDP 广播它的应用程序和连接信息。您的客户端可以侦听您的服务器自定义的所有广播数据包 header。假设已建立连接,您可以停止广播。缺点是如果客户端未连接,您将不得不不断广播,如果广播速度没有限制,这可能会阻塞您的网络。

编辑: 这是从 MSDN 文章 https://msdn.microsoft.com/en-us/library/tst0kwb1(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1

生成的归纳解释

编辑 #2: 我在我的博客上扩展了这个答案,并提供了可下载的示例项目。这篇文章可以在 http://martialdeveloper.com/wordpress/?p=21

找到

1.查找您网络的广播 IP

当使用 UDP 将数据报发送到连接到给定网络的所有机器时,必须使用特殊的“广播地址”。例如,192.168.0.1 的典型家庭网络 host/gateway 的广播地址为 192.168.0.255。如果您的网络与此不同,您可以使用像此处找到的 IPv4 广播地址计算器 http://jodies.de/ipcalc 或者阅读 MSDN 上描述广播地址的介绍部分。 https://msdn.microsoft.com/en-us/library/tst0kwb1(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1

2。 Select一个listening/broadcast端口

客户端和服务器上的任何空闲端口都可以。 MSDN 示例使用 11000。此端口号用于您的广播和侦听器。

3。侦听器代码

注意reader。为清楚起见,省略了所有错误处理。

int listenPort = 11000;
bool done = false;

UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any,listenPort);


while (!done) // This loop listens for your broadcast packets
{
    Console.WriteLine("Waiting for broadcast");
    byte[] bytes = listener.Receive( ref groupEP);

    Console.WriteLine("Received broadcast from {0} :\n {1}\n",
            groupEP.ToString(),
            Encoding.ASCII.GetString(bytes,0,bytes.Length));
}
listener.Close();

注:Console.WriteLine的第三个参数,"Encoding.ASCII..."表示数据报包中通过UDP发送的字符串值。这包含发现情况所需的协商信息,例如您希望连接到的客户端或服务器的 IP 地址。

4.广播员代码

Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
            ProtocolType.Udp);

IPAddress broadcast = IPAddress.Parse("This string should be the broadcast IP address");  //NOTE: Broadcast IP goes here!!

byte[] sendbuf = Encoding.ASCII.GetBytes("This is the message string to be broadcast"); //Your message to the client/server goes here, I.E. an
         // app/client name or ID and an IP to connect with over TCP

IPEndPoint ep = new IPEndPoint(broadcast, 11000);

s.SendTo(sendbuf, ep);

Console.WriteLine("Message sent to the broadcast address");

注意:这是一个非常简单的例子。广播者可能需要重播一段时间以确保收听者接收到它。即使在 UDP 数据报 sent/received 之后,也需要进行一些协商以确保正确建立 TCP 连接。