vb.net UDP本地广播
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16653306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UDP local broadcast
提问by Abandoned account
I'm working on a remote control tool. The client runs a program to locally send commands to servers in order to control them.
我正在研究远程控制工具。客户端运行一个程序在本地向服务器发送命令以控制它们。
However, the client doesn't know the server's IP address and vice versa.
但是,客户端不知道服务器的 IP 地址,反之亦然。
I decided to use UDP broadcasting (please tell me if there's a better way to do this, I tried using multicast but I didn't really understand it). When started, the client (which controls the servers) broadcasts a message to tell the servers that a new client connected. Then (or when the server is started), the servers broadcast their own IP addresses. When the client receives an IP address, it tries to connect via TCP.
我决定使用 UDP 广播(请告诉我是否有更好的方法来做到这一点,我尝试使用多播,但我并没有真正理解它)。启动时,客户端(控制服务器)广播一条消息告诉服务器有新客户端连接。然后(或当服务器启动时),服务器广播它们自己的 IP 地址。当客户端收到 IP 地址时,它会尝试通过 TCP 进行连接。
Unfortunately, I ran into problems with that. I randomly got An existing connection was forcibly closed by the remote hostexceptions and I wasn't able to find out why.
The exception occurred in my client program when listening for UDP broadcasts.
不幸的是,我遇到了问题。我随机得到了An existing connection was forcibly closed by the remote host例外,但我无法找出原因。我的客户端程序在侦听 UDP 广播时发生了异常。
Now, I'm looking for a better way to find the clients. Should I use broadcast or multicast? How would I implement that?
现在,我正在寻找一种更好的方式来寻找客户。我应该使用广播还是多播?我将如何实施?
EDIT: It wouldn't be a problem to use multiple ports. However, I need to be able to run a client AND a server on a single computer.
编辑:使用多个端口不会有问题。但是,我需要能够在一台计算机上运行客户端和服务器。
Here's the code I was using
这是我使用的代码
Client (controls servers)
客户端(控制服务器)
'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
Servers (controlled by client)
服务器(由客户端控制)
'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
Thanks in advance!
提前致谢!
回答by Abandoned account
Thank you for your answers. I fixedit by removing the feature to manually call StartBroadcastUdpThread()in my client.
谢谢您的回答。我通过删除手动调用客户端的功能来修复它StartBroadcastUdpThread()。
I still don't understand why this happens though. I use exactly the same code for both client and server, except the ports are swapped. The TCP server doesn't crash even if the StartBroadcastUdpThread()method is called multiple times, the client does. By the way, the problem occurs regardless of whether the client or server is started first.
我仍然不明白为什么会发生这种情况。我对客户端和服务器使用完全相同的代码,只是端口交换了。即使StartBroadcastUdpThread()多次调用该方法,TCP 服务器也不会崩溃,客户端会。顺便说一下,无论是先启动客户端还是服务器,都会出现问题。
Even if I don't really understand why broadcasting the second time stops the client from receiving broadcasts - it's fixed for now. Thanks for you help!
即使我真的不明白为什么第二次广播会阻止客户端接收广播 - 现在已经修复了。谢谢你的帮助!
回答by Arvy
Minimal UDP server basis:
最小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
回答by eile
I would suggest using Zeroconf to find the server and clients, and then use a TCP socket to communicate between the two. You can see an example implementation on key-value pair zeroconf announcements here: https://github.com/Eyescale/Lunchbox/blob/master/lunchbox/servus.cpp
我建议使用 Zeroconf 来查找服务器和客户端,然后使用 TCP 套接字在两者之间进行通信。您可以在此处查看键值对 zeroconf 公告的示例实现:https: //github.com/Eyescale/Lunchbox/blob/master/lunchbox/servus.cpp

