Mar*_*tus 2 c# sockets port networking udp
在一个项目中,有一个设备侦听特定的 UDP 端口并应答发送方端口。
对于发送方和接收方,我希望系统选择一个空闲端口,所以我有以下代码:
[请原谅大量代码,但这是显示发生的行为的最小示例]
发送代码:
public class UdpSender
{
public int Port = 0; // some initially random port
public UdpClient UdpServer { get; set; }
public UdpSender()
{
UdpServer = CreateUdpClient();
// save the portnumber chosen by system to reuse it
Port = ((IPEndPoint)(UdpServer.Client.LocalEndPoint)).Port;
}
private UdpClient CreateUdpClient()
{
if (UdpServer != null)
{
UdpServer.Close();
}
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, Port);
var udpServer = new UdpClient();
udpServer.ExclusiveAddressUse = false;
udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpServer.Client.Bind(localEndPoint);
return udpServer;
}
public void Send(byte[] arr)
{
UdpServer = CreateUdpClient();
int remotePortNumber = 6565;
var remoteEndPoint = new IPEndPoint(IPAddress.Broadcast, remotePortNumber);
try
{
UdpServer.Send(arr, arr.Length, remoteEndPoint);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
UdpServer.Close();
}
}
Run Code Online (Sandbox Code Playgroud)
接收码:
public class UDPListener
{
private static int portNumber;
private UdpClient udpClient = null;
public List<DeviceData> DeviceList = new List<DeviceData>();
public UDPListener(int port)
{
portNumber = port;
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, portNumber);
udpClient = new UdpClient();
udpClient.ExclusiveAddressUse = false;
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(localEndPoint);
udpClient.Client.ReceiveBufferSize = 1 << 23;
}
public void StartListening()
{
this.udpClient.BeginReceive(Receive, new object());
}
private void Receive(IAsyncResult ar)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, portNumber);
byte[] bytes = udpClient.EndReceive(ar, ref ip);
string message = Encoding.ASCII.GetString(bytes);
DeviceList.Add(new DeviceData(message));
StartListening();
}
}
Run Code Online (Sandbox Code Playgroud)
把它放在一起:
public class DeviceFinder
{
public IEnumerable<DeviceData> Find()
{
var sender = new UdpSender();
int port = sender.Port;
var listener = new UDPListener(port);
listener.StartListening();
sender.Send(new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 });
System.Threading.Thread.Sleep(5000); // wait some time for answers
return listener.DeviceList;
}
}
Run Code Online (Sandbox Code Playgroud)
Receive使用此方法永远不会调用该方法。但在 Wireshark 中,我可以看到来自设备的答案。
这种方法有什么问题吗?
CreateUdpClient在使用这种方法之前,我已经使用了固定端口,并且还添加了对的调用。似乎与此有关,但我无法弄清楚。在我刚刚UdpClient在接收/发送方法内部创建了一个带有固定端口的端口之前。
以前的版本可以在这个问题中看到。这非常有效。但我担心如果固定端口已经在使用中,它就不起作用,因此采用了这种新方法。