diff --git a/src/JT809Netty.Core/AtomicCounter.cs b/src/JT809Netty.Core/AtomicCounter.cs
new file mode 100644
index 0000000..9b4fcaa
--- /dev/null
+++ b/src/JT809Netty.Core/AtomicCounter.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace JT809Netty.Core
+{
+ ///
+ ///
+ /// ref:Grpc.Core.Internal
+ ///
+ public class AtomicCounter
+ {
+ long counter = 0;
+
+ public AtomicCounter(long initialCount = 0)
+ {
+ this.counter = initialCount;
+ }
+
+ public long Increment()
+ {
+ return Interlocked.Increment(ref counter);
+ }
+
+ public long Decrement()
+ {
+ return Interlocked.Decrement(ref counter);
+ }
+
+ public long Count
+ {
+ get
+ {
+ return Interlocked.Read(ref counter);
+ }
+ }
+ }
+}
diff --git a/src/JT809Netty.Core/Configs/JT809NettyOptions.cs b/src/JT809Netty.Core/Configs/JT809NettyOptions.cs
new file mode 100644
index 0000000..e802b77
--- /dev/null
+++ b/src/JT809Netty.Core/Configs/JT809NettyOptions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809Netty.Core.Configs
+{
+ public class JT809NettyOptions
+ {
+ public string Host { get; set; }
+ public int Port { get; set; }
+ public List IpWhiteList { get; set; } = new List();
+ public bool IpWhiteListDisabled { get; set; }
+ }
+}
diff --git a/src/JT809Netty.Core/Handlers/JT808ServiceHandler.cs b/src/JT809Netty.Core/Handlers/JT808ServiceHandler.cs
new file mode 100644
index 0000000..f6e88de
--- /dev/null
+++ b/src/JT809Netty.Core/Handlers/JT808ServiceHandler.cs
@@ -0,0 +1,77 @@
+using DotNetty.Buffers;
+using DotNetty.Transport.Channels;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using JT808.Protocol;
+using JT808.Protocol.Extensions;
+using DotNetty.Common.Utilities;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using JT808.Protocol.Exceptions;
+using System.Threading;
+
+namespace GPS.JT808NettyServer.Handlers
+{
+ public class JT808ServiceHandler : ChannelHandlerAdapter
+ {
+ private readonly ILogger logger;
+
+ private readonly JT808MsgIdHandler jT808MsgIdHandler;
+
+ public JT808ServiceHandler(
+ JT808MsgIdHandler jT808MsgIdHandler,
+ ILoggerFactory loggerFactory)
+ {
+ this.jT808MsgIdHandler = jT808MsgIdHandler;
+ logger = loggerFactory.CreateLogger();
+ }
+
+ public override void ChannelRead(IChannelHandlerContext context, object message)
+ {
+ var jT808RequestInfo = (JT808RequestInfo)message;
+ string receive = string.Empty;
+ try
+ {
+ if (logger.IsEnabled(LogLevel.Debug))
+ {
+ receive = jT808RequestInfo.OriginalBuffer.ToHexString();
+ }
+ Func handlerFunc;
+ if (jT808RequestInfo.JT808Package != null)
+ {
+ if (jT808MsgIdHandler.HandlerDict.TryGetValue(jT808RequestInfo.JT808Package.Header.MsgId, out handlerFunc))
+ {
+ IJT808Package jT808PackageImpl = handlerFunc(jT808RequestInfo, context);
+ if (jT808PackageImpl != null)
+ {
+ if (logger.IsEnabled(LogLevel.Debug))
+ {
+ logger.LogDebug("send>>>" + jT808PackageImpl.JT808Package.Header.MsgId.ToString() + "-" + JT808Serializer.Serialize(jT808PackageImpl.JT808Package).ToHexString());
+ //logger.LogDebug("send>>>" + jT808PackageImpl.JT808Package.Header.MsgId.ToString() + "-" + JsonConvert.SerializeObject(jT808PackageImpl.JT808Package));
+ }
+ // 需要注意:
+ // 1.下发应答必须要在类中重写 ChannelReadComplete 不然客户端接收不到消息
+ // context.WriteAsync(Unpooled.WrappedBuffer(JT808Serializer.Serialize(jT808PackageImpl.JT808Package)));
+ // 2.直接发送
+ context.WriteAndFlushAsync(Unpooled.WrappedBuffer(JT808Serializer.Serialize(jT808PackageImpl.JT808Package)));
+ }
+ }
+ }
+ }
+ catch (JT808Exception ex)
+ {
+ if (logger.IsEnabled(LogLevel.Error))
+ logger.LogError(ex, "JT808Exception receive<<<" + receive);
+ }
+ catch (Exception ex)
+ {
+ if (logger.IsEnabled(LogLevel.Error))
+ logger.LogError(ex, "Exception receive<<<" + receive);
+ }
+ }
+
+ public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();
+ }
+}
diff --git a/src/JT809Netty.Core/Handlers/JT809DecodeHandler.cs b/src/JT809Netty.Core/Handlers/JT809DecodeHandler.cs
new file mode 100644
index 0000000..9a55292
--- /dev/null
+++ b/src/JT809Netty.Core/Handlers/JT809DecodeHandler.cs
@@ -0,0 +1,64 @@
+using DotNetty.Buffers;
+using DotNetty.Codecs;
+using DotNetty.Transport.Channels;
+using JT809.Protocol;
+using JT809.Protocol.JT809Exceptions;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace JT809Netty.Core.Handlers
+{
+ ///
+ /// JT809解码
+ ///
+ public class JT809DecodeHandler : ByteToMessageDecoder
+ {
+ private readonly ILogger logger;
+
+ public JT809DecodeHandler(ILoggerFactory loggerFactory)
+ {
+ logger = loggerFactory.CreateLogger();
+ }
+
+ private static readonly AtomicCounter MsgSuccessCounter = new AtomicCounter();
+
+ private static readonly AtomicCounter MsgFailCounter = new AtomicCounter();
+
+ protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List