You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.7 KiB

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace EC.Onvif.RemoteDiscovery
{
public class OnvifUdpClient
{
private UdpClient client { get; set; }
public bool IsClosed { get; set; }
public OnvifUdpClient(IPEndPoint localpoint)
{
client = new UdpClient(localpoint)
{
EnableBroadcast = true
};
}
public async Task<int> SendProbeAsync(Guid messageId, IPEndPoint endPoint)
{
byte[] datagram = NewProbeMessage(messageId);
return await client?.SendAsync(datagram, datagram.Length, endPoint);
}
public async Task<UdpReceiveResult> ReceiveAsync()
{
return await client.ReceiveAsync();
}
public void Close()
{
client?.Close();
IsClosed = true;
}
public static byte[] NewProbeMessage(Guid messageId)
{
if (messageId == Guid.Empty)
{
throw new ArgumentException("messageId could not be Empty");
}
var probeMessagewithguid = string.Format(Constants.WS_PROBE_MESSAGE, messageId.ToString());
return Encoding.ASCII.GetBytes(probeMessagewithguid);
}
#region CreateClient
public static OnvifUdpClient CreateClient(NetworkInterface adapter)
{
if (!IsValidAdapter(adapter)) { return null; }
OnvifUdpClient client = null;
IPInterfaceProperties adapterProperties = adapter.GetIPProperties();
foreach (UnicastIPAddressInformation ua in adapterProperties.UnicastAddresses)
{
if (ua.Address.AddressFamily != AddressFamily.InterNetwork) { continue; }
IPEndPoint myLocalEndPoint = new(ua.Address, 0); // port does not matter
try
{
client = new(myLocalEndPoint);
}
catch (SocketException)
{
throw;
}
break;
}
return client;
}
public static IEnumerable<OnvifUdpClient> CreateClientList(IEnumerable<NetworkInterface> adapterList)
{
List<OnvifUdpClient> clientList = new();
foreach (NetworkInterface adapter in adapterList)
{
OnvifUdpClient client = CreateClient(adapter);
if (client != null) { clientList.Add(client); }
}
return clientList;
}
public static IEnumerable<OnvifUdpClient> CreateClientList()
{
IEnumerable<NetworkInterface> adapterList = GetVaildNetworkAdapters();
return CreateClientList(adapterList);
}
#endregion CreateClient
#region ClientHelper
public static List<NetworkInterface> GetNetworkAdapters()
{
NetworkInterface[] nifs = NetworkInterface.GetAllNetworkInterfaces();
return new(nifs);
}
public static List<NetworkInterface> GetVaildNetworkAdapters()
{
NetworkInterface[] nifs = NetworkInterface.GetAllNetworkInterfaces();
List<NetworkInterface> list = new();
foreach (NetworkInterface nif in nifs)
{
if (IsValidAdapter(nif)) { list.Add(nif); }
}
return list;
}
public static bool IsValidAdapter(NetworkInterface adapter)
{
// Only select interfaces that are Ethernet type and support IPv4 (important to minimize waiting time)
if (adapter.NetworkInterfaceType != NetworkInterfaceType.Ethernet &&
!adapter.NetworkInterfaceType.ToString().ToLower().StartsWith("wireless")) return false;
if (adapter.OperationalStatus == OperationalStatus.Down) { return false; }
if (!adapter.Supports(NetworkInterfaceComponent.IPv4)) { return false; }
return true;
}
/// <summary>
/// 广播
/// </summary>
/// <param name="client"></param>
/// <param name="messageId"></param>
/// <returns></returns>
public static async Task SendProbe(OnvifUdpClient client, Guid messageId)
{
IPEndPoint multicastEndpoint = new(IPAddress.Parse(Constants.WS_MULTICAST_ADDRESS), Constants.WS_MULTICAST_PORT);
await client.SendProbeAsync(messageId, multicastEndpoint);
}
#endregion ClientHelper
}
}