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.
136 lines
4.1 KiB
136 lines
4.1 KiB
2 years ago
|
using System.Net;
|
||
|
using System.Net.NetworkInformation;
|
||
|
using System.Net.Sockets;
|
||
|
using System.Text;
|
||
|
|
||
|
namespace EC.Helper.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
|
||
|
}
|