@@ -2,6 +2,7 @@ | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using DotNetty.Transport.Channels; | |||
using JT808.DotNetty.Metadata; | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.Logging; | |||
@@ -17,10 +18,10 @@ namespace JT808.DotNetty.Hosting | |||
logger = loggerFactory.CreateLogger<JT808MsgIdCustomHandler>(); | |||
} | |||
public override JT808Package Msg0x0102(JT808Package reqJT808Package, IChannelHandlerContext ctx) | |||
public override JT808Response Msg0x0102(JT808Request request) | |||
{ | |||
logger.LogDebug("Msg0x0102"); | |||
return base.Msg0x0102(reqJT808Package, ctx); | |||
return base.Msg0x0102(request); | |||
} | |||
} | |||
} |
@@ -4,6 +4,9 @@ using Microsoft.Extensions.DependencyInjection.Extensions; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Collections.Concurrent; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using System.Threading.Tasks; | |||
namespace JT808.DotNetty.Hosting | |||
@@ -30,7 +33,7 @@ namespace JT808.DotNetty.Hosting | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
// 自定义消息处理业务 | |||
services.Replace(new ServiceDescriptor(typeof(JT808MsgIdHandlerBase),typeof(JT808MsgIdCustomHandler),ServiceLifetime.Singleton)); | |||
services.Replace(new ServiceDescriptor(typeof(JT808MsgIdHandlerBase), typeof(JT808MsgIdCustomHandler), ServiceLifetime.Singleton)); | |||
}) | |||
.UseJT808Host(); | |||
await serverHostBuilder.RunConsoleAsync(); | |||
@@ -13,9 +13,13 @@ namespace JT808.DotNetty.Handlers | |||
{ | |||
private readonly ILogger<JT808ConnectionHandler> logger; | |||
private readonly JT808SessionManager jT808SessionManager; | |||
public JT808ConnectionHandler( | |||
JT808SessionManager jT808SessionManager, | |||
ILoggerFactory loggerFactory) | |||
{ | |||
this.jT808SessionManager = jT808SessionManager; | |||
logger = loggerFactory.CreateLogger<JT808ConnectionHandler>(); | |||
} | |||
@@ -40,6 +44,7 @@ namespace JT808.DotNetty.Handlers | |||
string channelId = context.Channel.Id.AsShortText(); | |||
if (logger.IsEnabled(LogLevel.Debug)) | |||
logger.LogDebug($">>>{ channelId } The client disconnects from the server."); | |||
jT808SessionManager.RemoveSessionByID(channelId); | |||
base.ChannelInactive(context); | |||
} | |||
@@ -53,6 +58,7 @@ namespace JT808.DotNetty.Handlers | |||
string channelId = context.Channel.Id.AsShortText(); | |||
if (logger.IsEnabled(LogLevel.Debug)) | |||
logger.LogDebug($"<<<{ channelId } The server disconnects from the client."); | |||
jT808SessionManager.RemoveSessionByID(channelId); | |||
return base.CloseAsync(context); | |||
} | |||
@@ -74,6 +80,7 @@ namespace JT808.DotNetty.Handlers | |||
string channelId = context.Channel.Id.AsShortText(); | |||
logger.LogInformation($"{idleStateEvent.State.ToString()}>>>{channelId}"); | |||
// 由于808是设备发心跳,如果很久没有上报数据,那么就由服务器主动关闭连接。 | |||
jT808SessionManager.RemoveSessionByID(channelId); | |||
context.CloseAsync(); | |||
} | |||
base.UserEventTriggered(context, evt); | |||
@@ -83,6 +90,7 @@ namespace JT808.DotNetty.Handlers | |||
{ | |||
string channelId = context.Channel.Id.AsShortText(); | |||
logger.LogError(exception,$"{channelId} {exception.Message}" ); | |||
jT808SessionManager.RemoveSessionByID(channelId); | |||
context.CloseAsync(); | |||
} | |||
} | |||
@@ -4,29 +4,34 @@ using JT808.Protocol; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using JT808.DotNetty.Metadata; | |||
namespace JT808.DotNetty.Handlers | |||
{ | |||
internal class JT808ServerHandler : SimpleChannelInboundHandler<JT808.Protocol.JT808Package> | |||
{ | |||
private readonly JT808MsgIdHandlerBase handler; | |||
private readonly JT808SessionManager jT808SessionManager; | |||
public JT808ServerHandler(JT808MsgIdHandlerBase handler) | |||
public JT808ServerHandler(JT808MsgIdHandlerBase handler, JT808SessionManager jT808SessionManager) | |||
{ | |||
this.handler = handler; | |||
this.jT808SessionManager = jT808SessionManager; | |||
} | |||
protected override void ChannelRead0(IChannelHandlerContext ctx, JT808Package msg) | |||
{ | |||
try | |||
{ | |||
Func<JT808Package, IChannelHandlerContext, JT808Package> handlerFunc; | |||
jT808SessionManager.TryAddOrUpdateSession(new JT808Session(ctx.Channel, msg.Header.TerminalPhoneNo)); | |||
Func<JT808Request, JT808Response> handlerFunc; | |||
if (handler.HandlerDict.TryGetValue(msg.Header.MsgId, out handlerFunc)) | |||
{ | |||
JT808Package jT808Package = handlerFunc(msg, ctx); | |||
JT808Response jT808Package = handlerFunc(new JT808Request(msg)); | |||
if (jT808Package != null) | |||
{ | |||
ctx.WriteAndFlushAsync(Unpooled.WrappedBuffer(JT808Serializer.Serialize(jT808Package))); | |||
ctx.WriteAndFlushAsync(Unpooled.WrappedBuffer(JT808Serializer.Serialize(jT808Package.Package))); | |||
} | |||
} | |||
} | |||
@@ -2,6 +2,7 @@ | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using DotNetty.Transport.Channels; | |||
using JT808.DotNetty.Metadata; | |||
using JT808.Protocol; | |||
using JT808.Protocol.Enums; | |||
using JT808.Protocol.Extensions; | |||
@@ -24,7 +25,7 @@ namespace JT808.DotNetty | |||
protected JT808MsgIdHandlerBase(JT808SessionManager sessionManager) | |||
{ | |||
this.sessionManager = sessionManager; | |||
HandlerDict = new Dictionary<JT808MsgId, Func<JT808Package, IChannelHandlerContext, JT808Package>> | |||
HandlerDict = new Dictionary<JT808MsgId, Func<JT808Request, JT808Response>> | |||
{ | |||
{JT808MsgId.终端通用应答, Msg0x0001}, | |||
{JT808MsgId.终端鉴权, Msg0x0102}, | |||
@@ -37,21 +38,21 @@ namespace JT808.DotNetty | |||
}; | |||
} | |||
public Dictionary<JT808MsgId, Func<JT808Package, IChannelHandlerContext, JT808Package>> HandlerDict { get; } | |||
public Dictionary<JT808MsgId, Func<JT808Request, JT808Response>> HandlerDict { get; } | |||
/// <summary> | |||
/// 终端通用应答 | |||
/// </summary> | |||
/// <param name="reqJT808Package"></param> | |||
/// <param name="ctx"></param> | |||
/// <returns></returns> | |||
public virtual JT808Package Msg0x0001(JT808Package reqJT808Package, IChannelHandlerContext ctx) | |||
public virtual JT808Response Msg0x0001(JT808Request request) | |||
{ | |||
return JT808MsgId.平台通用应答.Create(reqJT808Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = reqJT808Package.Header.MsgId, | |||
MsgId = request.Package.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.Success, | |||
MsgNum = reqJT808Package.Header.MsgNum | |||
}); | |||
MsgNum = request.Package.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 终端心跳 | |||
@@ -59,15 +60,15 @@ namespace JT808.DotNetty | |||
/// <param name="reqJT808Package"></param> | |||
/// <param name="ctx"></param> | |||
/// <returns></returns> | |||
public virtual JT808Package Msg0x0002(JT808Package reqJT808Package, IChannelHandlerContext ctx) | |||
public virtual JT808Response Msg0x0002(JT808Request request) | |||
{ | |||
sessionManager.Heartbeat(reqJT808Package.Header.TerminalPhoneNo); | |||
return JT808MsgId.平台通用应答.Create(reqJT808Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
sessionManager.Heartbeat(request.Package.Header.TerminalPhoneNo); | |||
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = reqJT808Package.Header.MsgId, | |||
MsgId = request.Package.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.Success, | |||
MsgNum = reqJT808Package.Header.MsgNum | |||
}); | |||
MsgNum = request.Package.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 终端注销 | |||
@@ -75,15 +76,14 @@ namespace JT808.DotNetty | |||
/// <param name="reqJT808Package"></param> | |||
/// <param name="ctx"></param> | |||
/// <returns></returns> | |||
public virtual JT808Package Msg0x0003(JT808Package reqJT808Package, IChannelHandlerContext ctx) | |||
public virtual JT808Response Msg0x0003(JT808Request request) | |||
{ | |||
sessionManager.RemoveSessionByTerminalPhoneNo(reqJT808Package.Header.TerminalPhoneNo); | |||
return JT808MsgId.平台通用应答.Create(reqJT808Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = reqJT808Package.Header.MsgId, | |||
MsgId = request.Package.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.Success, | |||
MsgNum = reqJT808Package.Header.MsgNum | |||
}); | |||
MsgNum = request.Package.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 终端注册 | |||
@@ -91,14 +91,14 @@ namespace JT808.DotNetty | |||
/// <param name="reqJT808Package"></param> | |||
/// <param name="ctx"></param> | |||
/// <returns></returns> | |||
public virtual JT808Package Msg0x0100(JT808Package reqJT808Package, IChannelHandlerContext ctx) | |||
public virtual JT808Response Msg0x0100(JT808Request request) | |||
{ | |||
return JT808MsgId.终端注册应答.Create(reqJT808Package.Header.TerminalPhoneNo, new JT808_0x8100() | |||
return new JT808Response(JT808MsgId.终端注册应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8100() | |||
{ | |||
Code = "J" + reqJT808Package.Header.TerminalPhoneNo, | |||
Code = "J" + request.Package.Header.TerminalPhoneNo, | |||
JT808TerminalRegisterResult = JT808TerminalRegisterResult.成功, | |||
MsgNum = reqJT808Package.Header.MsgNum | |||
}); | |||
MsgNum = request.Package.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 终端鉴权 | |||
@@ -106,15 +106,14 @@ namespace JT808.DotNetty | |||
/// <param name="reqJT808Package"></param> | |||
/// <param name="ctx"></param> | |||
/// <returns></returns> | |||
public virtual JT808Package Msg0x0102(JT808Package reqJT808Package, IChannelHandlerContext ctx) | |||
public virtual JT808Response Msg0x0102(JT808Request request) | |||
{ | |||
sessionManager.RegisterSession(new JT808Session(ctx.Channel, reqJT808Package.Header.TerminalPhoneNo)); | |||
return JT808MsgId.平台通用应答.Create(reqJT808Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = reqJT808Package.Header.MsgId, | |||
MsgId = request.Package.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.Success, | |||
MsgNum = reqJT808Package.Header.MsgNum | |||
}); | |||
MsgNum = request.Package.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 位置信息汇报 | |||
@@ -122,14 +121,14 @@ namespace JT808.DotNetty | |||
/// <param name="reqJT808Package"></param> | |||
/// <param name="ctx"></param> | |||
/// <returns></returns> | |||
public virtual JT808Package Msg0x0200(JT808Package reqJT808Package, IChannelHandlerContext ctx) | |||
public virtual JT808Response Msg0x0200(JT808Request request) | |||
{ | |||
return JT808MsgId.平台通用应答.Create(reqJT808Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = reqJT808Package.Header.MsgId, | |||
MsgId = request.Package.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.Success, | |||
MsgNum = reqJT808Package.Header.MsgNum | |||
}); | |||
MsgNum = request.Package.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 定位数据批量上传 | |||
@@ -137,14 +136,14 @@ namespace JT808.DotNetty | |||
/// <param name="reqJT808Package"></param> | |||
/// <param name="ctx"></param> | |||
/// <returns></returns> | |||
public virtual JT808Package Msg0x0704(JT808Package reqJT808Package, IChannelHandlerContext ctx) | |||
public virtual JT808Response Msg0x0704(JT808Request request) | |||
{ | |||
return JT808MsgId.平台通用应答.Create(reqJT808Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = reqJT808Package.Header.MsgId, | |||
MsgId = request.Package.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.Success, | |||
MsgNum = reqJT808Package.Header.MsgNum | |||
}); | |||
MsgNum = request.Package.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 数据上行透传 | |||
@@ -152,14 +151,14 @@ namespace JT808.DotNetty | |||
/// <param name="reqJT808Package"></param> | |||
/// <param name="ctx"></param> | |||
/// <returns></returns> | |||
public virtual JT808Package Msg0x0900(JT808Package reqJT808Package, IChannelHandlerContext ctx) | |||
public virtual JT808Response Msg0x0900(JT808Request request) | |||
{ | |||
return JT808MsgId.平台通用应答.Create(reqJT808Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = reqJT808Package.Header.MsgId, | |||
MsgId = request.Package.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.Success, | |||
MsgNum = reqJT808Package.Header.MsgNum | |||
}); | |||
MsgNum = request.Package.Header.MsgNum | |||
})); | |||
} | |||
} | |||
} |
@@ -9,6 +9,7 @@ using System.Linq; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using JT808.DotNetty.Metadata; | |||
namespace JT808.DotNetty | |||
{ | |||
@@ -60,19 +61,6 @@ namespace JT808.DotNetty | |||
} | |||
} | |||
public void RegisterSession(JT808Session appSession) | |||
{ | |||
if (TerminalPhoneNo_SessionId_Dict.ContainsKey(appSession.TerminalPhoneNo)) | |||
{ | |||
return; | |||
} | |||
if (SessionIdDict.TryAdd(appSession.SessionID, appSession) && | |||
TerminalPhoneNo_SessionId_Dict.TryAdd(appSession.TerminalPhoneNo, appSession.SessionID)) | |||
{ | |||
return; | |||
} | |||
} | |||
public JT808Session GetSessionByID(string sessionID) | |||
{ | |||
if (string.IsNullOrEmpty(sessionID)) | |||
@@ -136,31 +124,10 @@ namespace JT808.DotNetty | |||
} | |||
} | |||
/// <summary> | |||
/// 通过通道Id和设备终端号进行关联 | |||
/// </summary> | |||
/// <param name="sessionID"></param> | |||
/// <param name="terminalPhoneNo"></param> | |||
public void UpdateSessionByID(string sessionID, string terminalPhoneNo) | |||
public void TryAddOrUpdateSession(JT808Session appSession) | |||
{ | |||
try | |||
{ | |||
if (SessionIdDict.TryGetValue(sessionID, out JT808Session oldjT808Session)) | |||
{ | |||
oldjT808Session.TerminalPhoneNo = terminalPhoneNo; | |||
if (SessionIdDict.TryUpdate(sessionID, oldjT808Session, oldjT808Session)) | |||
{ | |||
TerminalPhoneNo_SessionId_Dict.AddOrUpdate(terminalPhoneNo, sessionID, (tpn, sid) => | |||
{ | |||
return sessionID; | |||
}); | |||
} | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
logger.LogError(ex, $"{sessionID},{terminalPhoneNo}"); | |||
} | |||
SessionIdDict.AddOrUpdate(appSession.SessionID, appSession, (x, y) => appSession); | |||
TerminalPhoneNo_SessionId_Dict.AddOrUpdate(appSession.TerminalPhoneNo, appSession.SessionID, (x, y) => appSession.SessionID); | |||
} | |||
public void RemoveSessionByID(string sessionID) | |||
@@ -181,8 +148,6 @@ namespace JT808.DotNetty | |||
{ | |||
logger.LogInformation($">>>{sessionID} Session Remove."); | |||
} | |||
// call GPS.JT808NettyServer.Handlers.JT808ConnectionHandler.CloseAsync | |||
session.Channel.CloseAsync(); | |||
} | |||
} | |||
catch (Exception ex) | |||
@@ -191,29 +156,6 @@ namespace JT808.DotNetty | |||
} | |||
} | |||
public void RemoveSessionByTerminalPhoneNo(string terminalPhoneNo) | |||
{ | |||
if (terminalPhoneNo == null) return; | |||
try | |||
{ | |||
if (TerminalPhoneNo_SessionId_Dict.TryRemove(terminalPhoneNo, out string sessionid)) | |||
{ | |||
if (SessionIdDict.TryRemove(sessionid, out JT808Session session)) | |||
{ | |||
logger.LogInformation($">>>{terminalPhoneNo}-{sessionid} TerminalPhoneNo Remove."); | |||
} | |||
else | |||
{ | |||
logger.LogInformation($">>>{terminalPhoneNo} TerminalPhoneNo Remove."); | |||
} | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
logger.LogError(ex, $">>>{terminalPhoneNo} TerminalPhoneNo Remove Exception."); | |||
} | |||
} | |||
public void Dispose() | |||
{ | |||
cancellationTokenSource.Cancel(); | |||
@@ -0,0 +1,21 @@ | |||
using JT808.Protocol; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Reflection; | |||
namespace JT808.DotNetty.Metadata | |||
{ | |||
public class JT808Request | |||
{ | |||
public JT808Package Package { get; set; } | |||
public JT808Request() | |||
{ | |||
} | |||
public JT808Request(JT808Package package) | |||
{ | |||
Package = package; | |||
} | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
using JT808.Protocol; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Reflection; | |||
namespace JT808.DotNetty.Metadata | |||
{ | |||
public class JT808Response | |||
{ | |||
public JT808Package Package { get; set; } | |||
public JT808Response() | |||
{ | |||
} | |||
public JT808Response(JT808Package package) | |||
{ | |||
Package = package; | |||
} | |||
} | |||
} |
@@ -3,7 +3,7 @@ using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.DotNetty | |||
namespace JT808.DotNetty.Metadata | |||
{ | |||
public class JT808Session | |||
{ |