using System; using System.Collections.Concurrent; using System.Text; using System.Threading.Tasks; namespace Plane.Communication { /// /// (通过DTU服务端的Udp透传管道)与飞机进行通信的连接器。 /// public partial class UdpThroughDtuServiceConnection : ExceptionThrownEventSource, IConnection { #region Fields private byte[] _currentByteArray; private int _currentIndex; #if LOG_PACKETS private System.Text.StringBuilder _log = new System.Text.StringBuilder(); #endif private ConcurrentQueue _inputQueue = new ConcurrentQueue(); /// /// 表示向DTU服务端飞控透传通道握手的协议头 /// protected string FLAG_DTU_HANDSHAKE_HEAD = "*#$"; /// /// 表示向DTU服务端的Udp飞控透传管道建立申请的结果状态 /// protected enum DTUHandShakeResult { Unknown = 0, Successful = 1, NotExisted, Occupied, } #endregion #region Properties /// /// 希望连接到哪台飞机 /// public string CopterIDToBind { get; set; } public bool IsOpen { get; private set; } /// /// 获取即将或正在与服务端连接的服务端IP /// public string DtuServiceIP { get; set; } /// /// 获取即将或正在与服务端连接的服务端端口 /// public int DtuServicePort { get; set; } #endregion public virtual async Task ReadAsync(byte[] buffer, int offset, int size) { if (!IsOpen) { return 0; } try { var indexLessThan = offset + size; for (int i = offset; i < indexLessThan; i++, _currentIndex++) { while (_currentByteArray == null || _currentIndex >= _currentByteArray.Length) { while (_inputQueue.Count <= 0) { if (!IsOpen) { return 0; } await Task.Delay(5).ConfigureAwait(false); } while (!_inputQueue.TryDequeue(out _currentByteArray)) { if (!IsOpen) { return 0; } await Task.Delay(5).ConfigureAwait(false); } _currentIndex = 0; } buffer[i] = _currentByteArray[_currentIndex]; } return size; } catch (Exception ex) { RaiseExceptionThrown(ex); return 0; } } public virtual async Task WriteAsync(byte[] buffer, int offset, int count) { if (IsOpen) { try { if (offset == 0) { await SendAsync(buffer, count); } else { var data = new byte[count]; for (int i = 0, j = offset; i < count; i++, j++) { data[i] = buffer[j]; } await SendAsync(data, count); } } catch (Exception ex) { Close(); RaiseExceptionThrown(ex); } } } internal void EnqueueDatagram(byte[] datagram) { if (datagram != null && IsOpen) { #if LOG_PACKETS _log.AppendLine("------------"); for (int i = 0; i < datagram.Length; i++) { _log.Append(datagram[i]).Append(" "); } _log.AppendLine(); #endif _inputQueue.Enqueue(datagram); } } /// /// 构建用于发向DTU服务端的握手包 /// /// protected virtual byte[] ConstructHandShakeDatagramToDTUService() { var str = string.Format("{0}{1}", FLAG_DTU_HANDSHAKE_HEAD, CopterIDToBind??string.Empty); return Encoding.ASCII.GetBytes(str); } /// /// 分析由DTU服务端返回的我握手包 /// /// /// protected virtual DTUHandShakeResult AnalyzeHandShakeDatagramFromDTUService(byte[] buffer) { var strResult = Encoding.ASCII.GetString(buffer);//返回的格式为“*#$xxxx|0” if (strResult.StartsWith(FLAG_DTU_HANDSHAKE_HEAD)) { var strList = strResult.Substring(FLAG_DTU_HANDSHAKE_HEAD.Length).Split('|'); var copterID = strList[0]; int iValue; int.TryParse(strList[1], out iValue); return (DTUHandShakeResult)iValue; } return DTUHandShakeResult.Unknown; } } }