| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- using System;
- using System.Collections.Concurrent;
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- using System.Threading.Tasks;
- using Newtonsoft.Json;
- using TeamAAS.Communication.Attributes;
- using TeamAAS.Communication.Base;
- using TeamAAS.Communication.Interfaces;
- namespace TeamAAS.Communication.Devices
- {
- /// <summary>
- /// UDP 通讯(数据报协议,无连接,广播/多播支持)。
- /// </summary>
- [Communication("UDP", "基础通讯", "UDP 数据报通讯")]
- public class UdpCommunication : BindableCommunicationBase
- {
- [JsonIgnore]
- private UdpClient _udpClient;
- private readonly ConcurrentQueue<string> _received = new ConcurrentQueue<string>();
- private string _localIp = "0.0.0.0";
- public string LocalIp
- {
- get { return _localIp; }
- set { if (SetProperty(ref _localIp, value)) Notify(nameof(EndpointUrl)); }
- }
- private int _localPort = 8888;
- public int LocalPort
- {
- get { return _localPort; }
- set { if (SetProperty(ref _localPort, value)) Notify(nameof(EndpointUrl)); }
- }
- private string _remoteIp = "127.0.0.1";
- public string RemoteIp
- {
- get { return _remoteIp; }
- set { if (SetProperty(ref _remoteIp, value)) Notify(nameof(EndpointUrl)); }
- }
- private int _remotePort = 9999;
- public int RemotePort
- {
- get { return _remotePort; }
- set { if (SetProperty(ref _remotePort, value)) Notify(nameof(EndpointUrl)); }
- }
- public override string EndpointUrl
- {
- get { return $"udp://{LocalIp}:{LocalPort} -> {RemoteIp}:{RemotePort}"; }
- set
- {
- if (!string.IsNullOrWhiteSpace(value) && value.StartsWith("udp://"))
- {
- var uri = new Uri(value);
- if (!string.IsNullOrWhiteSpace(uri.Host)) LocalIp = uri.Host;
- if (uri.Port > 0) LocalPort = uri.Port;
- }
- }
- }
- [JsonIgnore]
- public override bool IsConnected => _udpClient != null;
- public override event Action<object, bool> ConnectChangedEvent;
- public override event Action<object, string> DataReceivedEvent;
- public override void Connect()
- {
- Disconnect();
- IPAddress bindIp = IPAddress.Any;
- if (!string.IsNullOrWhiteSpace(LocalIp))
- {
- try { bindIp = IPAddress.Parse(LocalIp.Trim()); }
- catch { bindIp = IPAddress.Any; }
- }
- _udpClient = new UdpClient(LocalPort)
- {
- ExclusiveAddressUse = false
- };
- try
- {
- _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
- }
- catch { }
- _ = Task.Run(ReceiveLoop);
- ConnectChangedEvent?.Invoke(this, true);
- Notify(nameof(IsConnected));
- }
- public override Task ConnectAsync()
- {
- return Task.Run(() => Connect());
- }
- private async Task ReceiveLoop()
- {
- try
- {
- while (_udpClient != null)
- {
- var result = await _udpClient.ReceiveAsync();
- var text = Encoding.UTF8.GetString(result.Buffer, 0, result.Buffer.Length);
- _received.Enqueue(text);
- DataReceivedEvent?.Invoke(this, text);
- }
- }
- catch
- {
- }
- }
- public void Send(string text)
- {
- if (_udpClient == null)
- throw new InvalidOperationException("UDP 未连接。");
- var data = Encoding.UTF8.GetBytes(text ?? string.Empty);
- var endPoint = new IPEndPoint(IPAddress.Parse(RemoteIp), RemotePort);
- _udpClient.Send(data, data.Length, endPoint);
- }
- public void Send(byte[] data)
- {
- if (_udpClient == null)
- throw new InvalidOperationException("UDP 未连接。");
- var endPoint = new IPEndPoint(IPAddress.Parse(RemoteIp), RemotePort);
- _udpClient.Send(data, data.Length, endPoint);
- }
- public override object ReadValue(string address)
- {
- _received.TryDequeue(out var text);
- return text;
- }
- public override Task<object> ReadValueAsync(string address)
- {
- return Task.FromResult(ReadValue(address));
- }
- public override void WriteValue(string address, object value)
- {
- Send(value?.ToString() ?? string.Empty);
- }
- public override Task WriteValueAsync(string address, object value)
- {
- Send(value?.ToString() ?? string.Empty);
- return Task.CompletedTask;
- }
- public override void Disconnect()
- {
- if (_udpClient != null)
- {
- try { _udpClient.Close(); } catch { }
- _udpClient.Dispose();
- _udpClient = null;
- }
- ConnectChangedEvent?.Invoke(this, false);
- Notify(nameof(IsConnected));
- }
- public override void Dispose()
- {
- Disconnect();
- }
- }
- }
|