public Task StartAsync(CancellationToken cancellationToken) { Logger.LogInformation($"JT1078 Tcp Server start at {IPAddress.Any}:{Configuration.TcpPort}."); Task.Factory.StartNew(async() => { while (!cancellationToken.IsCancellationRequested) { var socket = await server.AcceptAsync(); JT1078TcpSession jT808TcpSession = new JT1078TcpSession(socket); SessionManager.TryAdd(jT808TcpSession); await Task.Factory.StartNew(async(state) => { var session = (JT1078TcpSession)state; if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"[Connected]:{session.Client.RemoteEndPoint}"); } var pipe = new Pipe(); Task writing = FillPipeAsync(session, pipe.Writer); Task reading = ReadPipeAsync(session, pipe.Reader); await Task.WhenAll(reading, writing); SessionManager.RemoveBySessionId(session.SessionID); }, jT808TcpSession); } }, cancellationToken); return(Task.CompletedTask); }
private async Task FillPipeAsync(JT1078TcpSession session, PipeWriter writer) { while (true) { try { Memory <byte> memory = writer.GetMemory(Configuration.MiniNumBufferSize); //设备多久没发数据就断开连接 Receive Timeout. int bytesRead = await session.Client.ReceiveAsync(memory, SocketFlags.None, session.ReceiveTimeout.Token); if (bytesRead == 0) { break; } writer.Advance(bytesRead); } catch (System.ObjectDisposedException ex) { } catch (OperationCanceledException ex) { Logger.LogError($"[Receive Timeout]:{session.Client.RemoteEndPoint}"); break; } catch (System.Net.Sockets.SocketException ex) { Logger.LogError($"[{ex.SocketErrorCode.ToString()},{ex.Message}]:{session.Client.RemoteEndPoint}"); break; } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) { Logger.LogError(ex, $"[Receive Error]:{session.Client.RemoteEndPoint}"); break; } #pragma warning restore CA1031 // Do not catch general exception types FlushResult result = await writer.FlushAsync(); if (result.IsCompleted) { break; } } writer.Complete(); }
private async Task ReadPipeAsync(JT1078TcpSession session, PipeReader reader) { FixedHeaderInfo fixedHeaderInfo = new FixedHeaderInfo(); while (true) { ReadResult result = await reader.ReadAsync(); if (result.IsCompleted) { break; } ReadOnlySequence <byte> buffer = result.Buffer; SequencePosition consumed = buffer.Start; SequencePosition examined = buffer.End; try { if (result.IsCanceled) { break; } if (buffer.Length > 0) { ReaderBuffer(ref buffer, fixedHeaderInfo, session, out consumed, out examined); } } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) { Logger.LogError(ex, $"[ReadPipe Error]:{session.Client.RemoteEndPoint}"); break; } #pragma warning restore CA1031 // Do not catch general exception types finally { reader.AdvanceTo(consumed, examined); } } reader.Complete(); }
private void ReaderBuffer(ref ReadOnlySequence <byte> buffer, JT1078TcpSession session, out SequencePosition consumed, out SequencePosition examined) { consumed = buffer.Start; examined = buffer.End; if (buffer.Length < 15) { throw new ArgumentException("not JT1078 package"); } SequenceReader <byte> seqReader = new SequenceReader <byte>(buffer); long totalConsumed = 0; while (!seqReader.End) { if ((seqReader.Length - seqReader.Consumed) < 15) { throw new ArgumentException("not JT1078 package"); } var header = seqReader.Sequence.Slice(seqReader.Consumed, 4); var headerValue = BinaryPrimitives.ReadUInt32BigEndian(header.FirstSpan); if (JT1078Package.FH == headerValue) { //sim var sim = ReadBCD(seqReader.Sequence.Slice(seqReader.Consumed + 8, 6).FirstSpan, 12); //根据数据类型处理对应的数据长度 seqReader.Advance(15); if (seqReader.TryRead(out byte dataType)) { JT1078Label3 label3 = new JT1078Label3(dataType); int bodyLength = 0; //透传的时候没有该字段 if (label3.DataType != JT1078DataType.透传数据) { //时间戳 bodyLength += 8; } //非视频帧时没有该字段 if (label3.DataType == JT1078DataType.视频I帧 || label3.DataType == JT1078DataType.视频P帧 || label3.DataType == JT1078DataType.视频B帧) { //上一个关键帧 + 上一帧 = 2 + 2 bodyLength += 4; } seqReader.Advance(bodyLength); var bodyLengthFirstSpan = seqReader.Sequence.Slice(seqReader.Consumed, 2).FirstSpan; //数据体长度 seqReader.Advance(2); bodyLength = BinaryPrimitives.ReadUInt16BigEndian(bodyLengthFirstSpan); //数据体 seqReader.Advance(bodyLength); if (string.IsNullOrEmpty(sim)) { sim = session.SessionID; } SessionManager.TryLink(sim, session); var package = seqReader.Sequence.Slice(totalConsumed, seqReader.Consumed - totalConsumed); try { if (jT1078UseType == JT1078UseType.Queue) { jT1078MsgProducer.ProduceAsync(sim, package.ToArray()); } else { jT1078PackageProducer.ProduceAsync(sim, JT1078Serializer.Deserialize(package.FirstSpan)); } } catch (Exception ex) { Logger.LogError(ex, $"[Parse]:{package.ToArray().ToHexString()}"); } totalConsumed += (seqReader.Consumed - totalConsumed); if (seqReader.End) { break; } } } } if (seqReader.Length == totalConsumed) { examined = consumed = buffer.End; } else { consumed = buffer.GetPosition(totalConsumed); } }
private void ReaderBuffer(ref ReadOnlySequence <byte> buffer, FixedHeaderInfo fixedHeaderInfo, JT1078TcpSession session, out SequencePosition consumed, out SequencePosition examined) { consumed = buffer.Start; examined = buffer.End; SequenceReader <byte> seqReader = new SequenceReader <byte>(buffer); long totalConsumed = 0; while (!seqReader.End) { if (seqReader.Length < 30) { fixedHeaderInfo.Reset(); break; } if (!fixedHeaderInfo.FoundHeader) { var header = seqReader.Sequence.Slice(0, 4); uint headerValue = BinaryPrimitives.ReadUInt32BigEndian(header.ToArray()); if (JT1078Package.FH == headerValue) { //sim if (string.IsNullOrEmpty(fixedHeaderInfo.SIM)) { fixedHeaderInfo.SIM = ReadBCD(seqReader.Sequence.Slice(8, 6).ToArray(), 12); fixedHeaderInfo.SIM = fixedHeaderInfo.SIM ?? session.SessionID; } //根据数据类型处理对应的数据长度 fixedHeaderInfo.TotalSize += 15; var dataType = seqReader.Sequence.Slice(fixedHeaderInfo.TotalSize, 1).FirstSpan[0]; fixedHeaderInfo.TotalSize += 1; int bodyLength = GetRealDataBodyLength(dataType); fixedHeaderInfo.TotalSize += bodyLength; var bodyLengthFirstSpan = seqReader.Sequence.Slice(fixedHeaderInfo.TotalSize, 2).ToArray(); fixedHeaderInfo.TotalSize += 2; //数据体长度 bodyLength = BinaryPrimitives.ReadUInt16BigEndian(bodyLengthFirstSpan); if (bodyLength < 0) { fixedHeaderInfo.Reset(); throw new ArgumentException("jt1078 package body length Error."); } if (bodyLength == 0)//数据体长度为0 { var package1 = seqReader.Sequence.Slice(0, fixedHeaderInfo.TotalSize).ToArray(); seqReader.Advance(fixedHeaderInfo.TotalSize); if (LogLogger.IsEnabled(LogLevel.Trace)) { LogLogger.LogTrace($"{package1.ToHexString()}"); } try { SessionManager.TryLink(fixedHeaderInfo.SIM, session); jT1078MsgProducer.ProduceAsync(fixedHeaderInfo.SIM, package1.ToArray()); } catch (Exception ex) { LogLogger.LogError($"[Error Parse 1]:{package1.ToHexString()}"); Logger.LogError(ex, $"[Error Parse 1]:{package1.ToHexString()}"); } finally { totalConsumed += seqReader.Consumed; seqReader = new SequenceReader <byte>(seqReader.Sequence.Slice(fixedHeaderInfo.TotalSize)); fixedHeaderInfo.Reset(); #if DEBUG Interlocked.Increment(ref Counter); #endif } continue; } //数据体 fixedHeaderInfo.TotalSize += bodyLength; fixedHeaderInfo.FoundHeader = true; } else { fixedHeaderInfo.Reset(); throw new ArgumentException("not JT1078 package."); } } if ((seqReader.Length - fixedHeaderInfo.TotalSize) < 0) { break; } var package = seqReader.Sequence.Slice(0, fixedHeaderInfo.TotalSize).ToArray(); seqReader.Advance(fixedHeaderInfo.TotalSize); if (LogLogger.IsEnabled(LogLevel.Trace)) { LogLogger.LogTrace($"===>{package.ToHexString()}"); } try { SessionManager.TryLink(fixedHeaderInfo.SIM, session); jT1078MsgProducer.ProduceAsync(fixedHeaderInfo.SIM, package); } catch (Exception ex) { LogLogger.LogError($"[Error Parse 2]:{package.ToHexString()}"); Logger.LogError(ex, $"[Error Parse 2]:{package.ToHexString()}"); } finally { totalConsumed += seqReader.Consumed; seqReader = new SequenceReader <byte>(seqReader.Sequence.Slice(fixedHeaderInfo.TotalSize)); fixedHeaderInfo.Reset(); #if DEBUG Interlocked.Increment(ref Counter); #endif } #if DEBUG if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace($"======>{Counter}"); } #endif } if (seqReader.End) { examined = consumed = buffer.End; } else { consumed = buffer.GetPosition(totalConsumed); } }