【问题标题】:UDP local broadcastUDP本地广播
【发布时间】:2013-05-15 05:37:48
【问题描述】:

我正在开发远程控制工具。客户端运行一个程序在本地向服务器发送命令以控制它们。

但是,客户端不知道服务器的 IP 地址,反之亦然。

我决定使用 UDP 广播(请告诉我是否有更好的方法来做到这一点,我尝试使用多播但我并不真正理解它)。启动时,客户端(控制服务器)会广播一条消息,告诉服务器有新客户端连接。然后(或在服务器启动时),服务器广播它们自己的 IP 地址。当客户端收到 IP 地址时,它会尝试通过 TCP 连接。

不幸的是,我遇到了问题。我随机得到An existing connection was forcibly closed by the remote host 异常,但我无法找出原因。 我的客户端程序在监听 UDP 广播时发生异常。

现在,我正在寻找一种更好的方式来寻找客户。 我应该使用广播还是多播? 我将如何实现它?

编辑:使用多个端口不会有问题。但是,我需要能够在单台计算机上运行客户端和服务器。


这是我使用的代码

客户端(控制服务器)

'Variables
    Private UdpBroadcaster As UdpClient
    Private UdpBroadcasterEndpoint As New IPEndPoint(IPAddress.Broadcast, 4334)


'Sub New()
    Try
        UdpBroadcaster = New UdpClient(4333)
        UdpBroadcaster.EnableBroadcast = True
    Catch
        MsgBox("Error creating UDP client! Port already in use?", ...)
    End Try

'Called when the application starts
Private Sub StartUdpListener()
    Dim ListenerUdp As New Thread(AddressOf UdpListener)
    ListenerUdp.IsBackground = True
    ListenerUdp.Start()
End Sub

'Started as thread in StartUdpListener()
Private Sub UdpListener()
    Try
        Do
            'The next line fails with the error I described (An existing connection was forcibly closed by the remote host)
            Dim ReceivedBytes() As Byte = UdpBroadcaster.Receive(UdpBroadcasterEndpoint)
            Dim ReceivedString As String = System.Text.Encoding.UTF32.GetString(ReceivedBytes)

            'The following three lines will just connect to the received hostname
            Dim ScanThread As New Thread(Sub() ScanSingle(ReceivedString))
            ScanThread.IsBackground = True
            ScanThread.Start()
        Loop
    Catch
        If Not UdpBroadcaster Is Nothing Then
            UdpBroadcaster.Close()
            UdpBroadcaster = Nothing
        End If

        InvokeStatus("UDP connection lost, please try again later.")
    End Try
End Sub

'Called when the application starts and when the user manually clicks the "UDP Scan" button
Private Sub StartBroadcastUdpThread()
    Dim UdpBroadcastThread As New Thread(Sub() BroadcastUdp())
    UdpBroadcastThread.IsBackground = True
    UdpBroadcastThread.Start()
End Sub

'Started as thread in StartBroadcastUdpThread()
Private Sub BroadcastUdp()
    If UdpBroadcaster Is Nothing Then
        Try
            UdpBroadcaster = New UdpClient(4333)
            UdpBroadcaster.EnableBroadcast = True
        Catch
            MsgBox("Error creating UDP Client.", MsgBoxStyle.Critical, "Error")
            Application.Exit()
            Return
        End Try
    End If

    Dim BroadcastBytes() As Byte = System.Text.Encoding.UTF32.GetBytes("Client-Identify")
    UdpBroadcaster.Send(BroadcastBytes, BroadcastBytes.Length, UdpBroadcasterEndpoint)
    InvokeStatus("UDP request sent successfully")
End Sub



服务器(由客户端控制)

'Variables
Private UdpBroadcaster As UdpClient
Private UdpBroadcasterEndpoint As New IPEndPoint(IPAddress.Broadcast, 4333)

'Main method
Public Sub Main()
    Try
        UdpBroadcaster = New UdpClient(4334)
        UdpBroadcaster.EnableBroadcast = True

        StartUdpListener()
        StartBroadcastUdpThread()
    Catch
        Console.WriteLine("Failed to create server. Port already in use?")
    End Try
End Sub

'Called in Main()
Private Sub StartUdpListener()
    Dim ListenerUdp As New Thread(AddressOf UdpListener)
    ListenerUdp.IsBackground = True
    ListenerUdp.Start()
End Sub

'Started as thread in StartUdpListener()
Private Sub UdpListener()
    Try
        Do
            Dim ReceivedBytes() As Byte = UdpBroadcaster.Receive(UdpBroadcasterEndpoint)
            Dim ReceivedString As String = System.Text.Encoding.UTF32.GetString(ReceivedBytes)

            If ReceivedString.Equals("Client-Identify") Then
                StartBroadcastUdpThread()
            End If
        Loop
    Catch
        If Not UdpBroadcaster Is Nothing Then
            UdpBroadcaster.Close()
        End If
    End Try
End Sub

'Called when the application is started or a "Client-Identify" command is received
Private Sub StartBroadcastUdpThread()
    Dim UdpBroadcastThread As New Thread(Sub() BroadcastUdp())
    UdpBroadcastThread.IsBackground = True
    UdpBroadcastThread.Start()
End Sub

'Started as thread in StartBroadcastUdpThread()
Private Sub BroadcastUdp()
    Dim BroadcastBytes() As Byte = System.Text.Encoding.UTF32.GetBytes(Dns.GetHostName)
    UdpBroadcaster.Send(BroadcastBytes, BroadcastBytes.Length, UdpBroadcasterEndpoint)
End Sub

提前致谢!

【问题讨论】:

  • 您是否检查了两台机器上的防火墙设置?
  • 我用单机测试了一下,防火墙设置没问题。我什至完全禁用了防火墙。顺便说一句,连接确实有效,我能够正确接收所有广播,它只是在第二次广播后断开我的连接。

标签: vb.net udp broadcast multicast udpclient


【解决方案1】:

感谢您的回答。我修复了它,删除了在我的客户端中手动调用StartBroadcastUdpThread() 的功能。

我仍然不明白为什么会发生这种情况。我对客户端和服务器使用完全相同的代码,只是交换了端口。即使多次调用StartBroadcastUdpThread() 方法,TCP 服务器也不会崩溃,客户端会。顺便说一句,不管先启动客户端还是服务器,都会出现问题。

即使我真的不明白为什么第二次广播会阻止客户端接收广播 - 它现在已修复。感谢您的帮助!

【讨论】:

    【解决方案2】:

    我建议使用 Zeroconf 来查找服务器和客户端,然后使用 TCP 套接字在两者之间进行通信。您可以在此处查看键值对 zeroconf 公告的示例实现:https://github.com/Eyescale/Lunchbox/blob/master/lunchbox/servus.cpp

    【讨论】:

      【解决方案3】:

      最小的UDP服务器基础:

      Imports System.Threading
      
      Shared client As UdpClient
      Shared receivePoint As IPEndPoint
      
      client = New UdpClient(2828) 'Port
      receivePoint = New IPEndPoint(New IPAddress(0), 0)
      
      Dim readThread As Thread = New Thread(New ThreadStart(AddressOf WaitForPackets))
      readThread.Start()
      
      Public Shared Sub WaitForPackets()
          While True
              Dim data As Byte() = client.Receive(receivePoint)
              Console.WriteLine("=" + System.Text.Encoding.ASCII.GetString(data))
          End While
      End Sub
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-31
        • 1970-01-01
        • 2017-04-19
        • 1970-01-01
        • 1970-01-01
        • 2012-03-07
        • 2016-02-25
        • 2011-02-22
        相关资源
        最近更新 更多