@@ -330,3 +330,4 @@ ASALocalRun/ | |||||
.mfractor/ | .mfractor/ | ||||
/nupkgs | /nupkgs | ||||
/src/JT808.DotNetty.Admin/tools/protoc-gen-grpc-web-1.0.3-windows-x86_64.exe | /src/JT808.DotNetty.Admin/tools/protoc-gen-grpc-web-1.0.3-windows-x86_64.exe | ||||
/src/JT808.Gateway.Benchmark/JT808.Gateway.CleintBenchmark/.config/dotnet-tools.json |
@@ -40,7 +40,7 @@ namespace JT808.Gateway.SimpleClient.Jobs | |||||
}); | }); | ||||
var result4 = await jT808HttpClient.QueryTcpSessionByTerminalPhoneNo(new Abstractions.Dtos.JT808TerminalPhoneNoDto { TerminalPhoneNo= "33333333333" }); | var result4 = await jT808HttpClient.QueryTcpSessionByTerminalPhoneNo(new Abstractions.Dtos.JT808TerminalPhoneNoDto { TerminalPhoneNo= "33333333333" }); | ||||
Logger.LogInformation($"[GetTcpAtomicCounter]:{JsonSerializer.Serialize(result2)}"); | Logger.LogInformation($"[GetTcpAtomicCounter]:{JsonSerializer.Serialize(result2)}"); | ||||
Logger.LogInformation($"[GetTcpSessionAll]:{JsonSerializer.Serialize(result3)}"); | |||||
Logger.LogInformation($"[UnificationSend]:{JsonSerializer.Serialize(result3)}"); | |||||
Logger.LogInformation($"[QueryTcpSessionByTerminalPhoneNo]:{JsonSerializer.Serialize(result4)}"); | Logger.LogInformation($"[QueryTcpSessionByTerminalPhoneNo]:{JsonSerializer.Serialize(result4)}"); | ||||
Thread.Sleep(3000); | Thread.Sleep(3000); | ||||
} | } | ||||
@@ -1 +1,3 @@ | |||||
dotnet publish ./JT808.Gateway.SimpleServer/JT808.Gateway.SimpleServer.csproj -c Release -o .output -r linux-x64 -p:PublishSingleFile=true -p:PublishTrimmed=true -p:IncludeNativeLibrariesForSelfExtract=true -p:DebugType=none -p:DebugSymbols=false | |||||
dotnet publish ./JT808.Gateway.SimpleServer/JT808.Gateway.SimpleServer.csproj -c Release -o .output -r linux-x64 -p:PublishSingleFile=true -p:PublishTrimmed=true -p:IncludeNativeLibrariesForSelfExtract=true -p:DebugType=none -p:DebugSymbols=false | |||||
dotnet publish ./JT808.Gateway.SimpleServer/JT808.Gateway.SimpleServer.csproj -c Release -o .output -r win-x64 -p:PublishSingleFile=true -p:PublishTrimmed=true -p:IncludeNativeLibrariesForSelfExtract=true -p:DebugType=none -p:DebugSymbols=false |
@@ -151,14 +151,14 @@ namespace JT808.Gateway.Test.Session | |||||
[Fact] | [Fact] | ||||
public void SendTest() | public void SendTest() | ||||
{ | { | ||||
Assert.ThrowsAsync<SocketException>(async () => | |||||
Assert.Throws<SocketException>(() => | |||||
{ | { | ||||
string tno = "123456"; | string tno = "123456"; | ||||
JT808SessionManager jT808SessionManager = new JT808SessionManager(new LoggerFactory()); | JT808SessionManager jT808SessionManager = new JT808SessionManager(new LoggerFactory()); | ||||
var session = new JT808TcpSession(new Socket(SocketType.Stream, ProtocolType.Tcp)); | var session = new JT808TcpSession(new Socket(SocketType.Stream, ProtocolType.Tcp)); | ||||
var result1 = jT808SessionManager.TryAdd(session); | var result1 = jT808SessionManager.TryAdd(session); | ||||
jT808SessionManager.TryLink(tno, session); | jT808SessionManager.TryLink(tno, session); | ||||
await jT808SessionManager.TrySendByTerminalPhoneNoAsync(tno, new byte[] { 0x7e, 0, 0, 0x7e }); | |||||
jT808SessionManager.TrySendByTerminalPhoneNoAsync(tno, new byte[] { 0x7e, 0, 0, 0x7e }); | |||||
}); | }); | ||||
} | } | ||||
@@ -19,7 +19,7 @@ namespace JT808.Gateway.Extensions | |||||
context.Response.Close(); | context.Response.Close(); | ||||
} | } | ||||
public static async ValueTask Http401(this HttpListenerContext context) | |||||
public static void Http401(this HttpListenerContext context) | |||||
{ | { | ||||
byte[] b = Encoding.UTF8.GetBytes("auth error"); | byte[] b = Encoding.UTF8.GetBytes("auth error"); | ||||
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; | context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; | ||||
@@ -27,12 +27,12 @@ namespace JT808.Gateway.Extensions | |||||
context.Response.KeepAlive = false; | context.Response.KeepAlive = false; | ||||
context.Response.ContentLength64 = b.Length; | context.Response.ContentLength64 = b.Length; | ||||
var output = context.Response.OutputStream; | var output = context.Response.OutputStream; | ||||
await output.WriteAsync(b, CancellationToken.None); | |||||
output.Write(b, 0, b.Length); | |||||
context.Response.OutputStream.Close(); | context.Response.OutputStream.Close(); | ||||
context.Response.Close(); | context.Response.Close(); | ||||
} | } | ||||
public static async ValueTask Http400(this HttpListenerContext context) | |||||
public static void Http400(this HttpListenerContext context) | |||||
{ | { | ||||
byte[] b = Encoding.UTF8.GetBytes($"sim and channel parameter required."); | byte[] b = Encoding.UTF8.GetBytes($"sim and channel parameter required."); | ||||
context.Response.StatusCode = (int)HttpStatusCode.BadRequest; | context.Response.StatusCode = (int)HttpStatusCode.BadRequest; | ||||
@@ -40,7 +40,7 @@ namespace JT808.Gateway.Extensions | |||||
context.Response.ContentType = jsonType; | context.Response.ContentType = jsonType; | ||||
context.Response.ContentLength64 = b.Length; | context.Response.ContentLength64 = b.Length; | ||||
var output = context.Response.OutputStream; | var output = context.Response.OutputStream; | ||||
await output.WriteAsync(b, CancellationToken.None); | |||||
output.Write(b, 0, b.Length); | |||||
context.Response.OutputStream.Close(); | context.Response.OutputStream.Close(); | ||||
context.Response.Close(); | context.Response.Close(); | ||||
} | } | ||||
@@ -63,7 +63,7 @@ namespace JT808.Gateway.Extensions | |||||
context.Response.Close(); | context.Response.Close(); | ||||
} | } | ||||
public static async ValueTask Http500(this HttpListenerContext context) | |||||
public static void Http500(this HttpListenerContext context) | |||||
{ | { | ||||
byte[] b = Encoding.UTF8.GetBytes("inner error"); | byte[] b = Encoding.UTF8.GetBytes("inner error"); | ||||
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; | context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; | ||||
@@ -71,43 +71,30 @@ namespace JT808.Gateway.Extensions | |||||
context.Response.ContentType = jsonType; | context.Response.ContentType = jsonType; | ||||
context.Response.ContentLength64 = b.Length; | context.Response.ContentLength64 = b.Length; | ||||
var output = context.Response.OutputStream; | var output = context.Response.OutputStream; | ||||
await output.WriteAsync(b,CancellationToken.None); | |||||
output.Write(b,0, b.Length); | |||||
context.Response.OutputStream.Close(); | context.Response.OutputStream.Close(); | ||||
context.Response.Close(); | context.Response.Close(); | ||||
} | } | ||||
public static async ValueTask Http504(this HttpListenerContext context) | |||||
{ | |||||
byte[] b = Encoding.UTF8.GetBytes("call service timeout."); | |||||
context.Response.StatusCode = (int)HttpStatusCode.GatewayTimeout; | |||||
context.Response.KeepAlive = false; | |||||
context.Response.ContentType = jsonType; | |||||
context.Response.ContentLength64 = b.Length; | |||||
var output = context.Response.OutputStream; | |||||
await output.WriteAsync(b, CancellationToken.None); | |||||
context.Response.OutputStream.Close(); | |||||
context.Response.Close(); | |||||
} | |||||
public static async ValueTask HttpSend(this HttpListenerContext context, ReadOnlyMemory<byte> buffer) | |||||
public static void HttpSend(this HttpListenerContext context, ReadOnlyMemory<byte> buffer) | |||||
{ | { | ||||
context.Response.StatusCode = (int)HttpStatusCode.OK; | context.Response.StatusCode = (int)HttpStatusCode.OK; | ||||
context.Response.KeepAlive = true; | |||||
context.Response.KeepAlive = false; | |||||
context.Response.ContentType = jsonType; | context.Response.ContentType = jsonType; | ||||
context.Response.ContentLength64 = buffer.Length; | context.Response.ContentLength64 = buffer.Length; | ||||
await context.Response.OutputStream.WriteAsync(buffer); | |||||
context.Response.OutputStream.Write(buffer.ToArray(),0, buffer.Length); | |||||
context.Response.OutputStream.Close(); | context.Response.OutputStream.Close(); | ||||
context.Response.Close(); | context.Response.Close(); | ||||
} | } | ||||
public static async ValueTask HttpSend(this HttpListenerContext context, string json) | |||||
public static void HttpSend(this HttpListenerContext context, string json) | |||||
{ | { | ||||
byte[] b = Encoding.UTF8.GetBytes(json); | byte[] b = Encoding.UTF8.GetBytes(json); | ||||
context.Response.StatusCode = (int)HttpStatusCode.OK; | context.Response.StatusCode = (int)HttpStatusCode.OK; | ||||
context.Response.KeepAlive = true; | |||||
context.Response.KeepAlive = false; | |||||
context.Response.ContentType = jsonType; | context.Response.ContentType = jsonType; | ||||
context.Response.ContentLength64 = b.Length; | context.Response.ContentLength64 = b.Length; | ||||
await context.Response.OutputStream.WriteAsync(b); | |||||
context.Response.OutputStream.Write(b,0, b.Length); | |||||
context.Response.OutputStream.Close(); | context.Response.OutputStream.Close(); | ||||
context.Response.Close(); | context.Response.Close(); | ||||
} | } | ||||
@@ -33,8 +33,6 @@ namespace JT808.Gateway | |||||
private readonly JT808MsgIdDefaultWebApiHandler MsgIdDefaultWebApiHandler; | private readonly JT808MsgIdDefaultWebApiHandler MsgIdDefaultWebApiHandler; | ||||
const int CallTimeoutMS = 10000; | |||||
public JT808HttpServer( | public JT808HttpServer( | ||||
JT808MsgIdDefaultWebApiHandler jT808MsgIdDefaultWebApiHandler, | JT808MsgIdDefaultWebApiHandler jT808MsgIdDefaultWebApiHandler, | ||||
IOptions<JT808Configuration> jT808ConfigurationAccessor, | IOptions<JT808Configuration> jT808ConfigurationAccessor, | ||||
@@ -66,11 +64,11 @@ namespace JT808.Gateway | |||||
Logger.LogWarning(ex, $"{ex.Message}:使用cmd命令[netsh http add urlacl url=http://*:{Configuration.WebApiPort}/ user=Everyone]"); | Logger.LogWarning(ex, $"{ex.Message}:使用cmd命令[netsh http add urlacl url=http://*:{Configuration.WebApiPort}/ user=Everyone]"); | ||||
} | } | ||||
Logger.LogInformation($"JT808 Http Server start at {IPAddress.Any}:{Configuration.WebApiPort}."); | Logger.LogInformation($"JT808 Http Server start at {IPAddress.Any}:{Configuration.WebApiPort}."); | ||||
Task.Factory.StartNew(async () => | |||||
Task.Factory.StartNew(() => | |||||
{ | { | ||||
while (listener.IsListening) | while (listener.IsListening) | ||||
{ | { | ||||
var context = await listener.GetContextAsync(); | |||||
var context = listener.GetContext(); | |||||
try | try | ||||
{ | { | ||||
if (context.Request.RawUrl.StartsWith("/favicon.ico")) | if (context.Request.RawUrl.StartsWith("/favicon.ico")) | ||||
@@ -90,21 +88,31 @@ namespace JT808.Gateway | |||||
} | } | ||||
if (authorization.Authorization(context, out var principal)) | if (authorization.Authorization(context, out var principal)) | ||||
{ | { | ||||
await ProcessRequestAsync(context, principal); | |||||
DateTime start = DateTime.Now; | |||||
if (Logger.IsEnabled(LogLevel.Debug)) | |||||
{ | |||||
Logger.LogDebug($"ProcessRequestAsync Start:{context.Request.RemoteEndPoint}-{context.Request.RawUrl}"); | |||||
} | |||||
ProcessRequest(context, principal); | |||||
if (Logger.IsEnabled(LogLevel.Debug)) | |||||
{ | |||||
double time = (DateTime.Now - start).TotalMilliseconds; | |||||
Logger.LogDebug($"ProcessRequestAsync End:{context.Request.RemoteEndPoint}-{context.Request.RawUrl} {time}ms"); | |||||
} | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
await context.Http401(); | |||||
context.Http401(); | |||||
} | } | ||||
} | } | ||||
catch (AggregateException ex) | catch (AggregateException ex) | ||||
{ | { | ||||
await context.Http500(); | |||||
context.Http500(); | |||||
Logger.LogError(ex, ex.StackTrace); | Logger.LogError(ex, ex.StackTrace); | ||||
} | } | ||||
catch (Exception ex) | catch (Exception ex) | ||||
{ | { | ||||
await context.Http500(); | |||||
context.Http500(); | |||||
Logger.LogError(ex, ex.StackTrace); | Logger.LogError(ex, ex.StackTrace); | ||||
} | } | ||||
} | } | ||||
@@ -112,7 +120,7 @@ namespace JT808.Gateway | |||||
return Task.CompletedTask; | return Task.CompletedTask; | ||||
} | } | ||||
private async ValueTask ProcessRequestAsync(HttpListenerContext context, IPrincipal principal) | |||||
private void ProcessRequest(HttpListenerContext context, IPrincipal principal) | |||||
{ | { | ||||
var router = MsgIdDefaultWebApiHandler.HandlerDict.FirstOrDefault(f => context.Request.RawUrl.StartsWith(f.Key)); | var router = MsgIdDefaultWebApiHandler.HandlerDict.FirstOrDefault(f => context.Request.RawUrl.StartsWith(f.Key)); | ||||
if (router.Key == null) | if (router.Key == null) | ||||
@@ -120,7 +128,6 @@ namespace JT808.Gateway | |||||
context.Http404(); | context.Http404(); | ||||
return; | return; | ||||
} | } | ||||
bool timeout=false; | |||||
byte[] response; | byte[] response; | ||||
if (context.Request.HttpMethod == HttpMethod.Get.Method) | if (context.Request.HttpMethod == HttpMethod.Get.Method) | ||||
{ | { | ||||
@@ -128,27 +135,13 @@ namespace JT808.Gateway | |||||
if (index > 0) | if (index > 0) | ||||
{ | { | ||||
var uriParamStr = context.Request.Url.AbsoluteUri[(index + 1)..].ToString(); | var uriParamStr = context.Request.Url.AbsoluteUri[(index + 1)..].ToString(); | ||||
response = Call(uriParamStr, router.Value, out timeout); | |||||
if (!timeout) | |||||
{ | |||||
await context.HttpSend(response); | |||||
} | |||||
else | |||||
{ | |||||
await context.Http504(); | |||||
} | |||||
response = router.Value(uriParamStr); | |||||
context.HttpSend(response); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
response = Call("", router.Value, out timeout); | |||||
if (!timeout) | |||||
{ | |||||
await context.HttpSend(response); | |||||
} | |||||
else | |||||
{ | |||||
await context.Http504(); | |||||
} | |||||
response = router.Value(""); | |||||
context.HttpSend(response); | |||||
} | } | ||||
} | } | ||||
else if(context.Request.HttpMethod == HttpMethod.Post.Method) | else if(context.Request.HttpMethod == HttpMethod.Post.Method) | ||||
@@ -158,15 +151,8 @@ namespace JT808.Gateway | |||||
{ | { | ||||
json = reader.ReadToEnd(); | json = reader.ReadToEnd(); | ||||
} | } | ||||
response = Call(json, router.Value, out timeout); | |||||
if (!timeout) | |||||
{ | |||||
await context.HttpSend(response); | |||||
} | |||||
else | |||||
{ | |||||
await context.Http504(); | |||||
} | |||||
response = router.Value(json); | |||||
context.HttpSend(response); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -174,23 +160,6 @@ namespace JT808.Gateway | |||||
} | } | ||||
} | } | ||||
private byte[] Call(string data, Func<string, byte[]> method,out bool timeout) | |||||
{ | |||||
try | |||||
{ | |||||
using CancellationTokenSource cancelSource1 = new CancellationTokenSource(CallTimeoutMS); | |||||
Task<byte[]> result = Task.Run(() => method(data), cancelSource1.Token); | |||||
result.Wait(cancelSource1.Token); | |||||
timeout = false; | |||||
return result.Result; | |||||
} | |||||
catch (OperationCanceledException) | |||||
{ | |||||
timeout = true; | |||||
} | |||||
return default(byte[]); | |||||
} | |||||
public Task StopAsync(CancellationToken cancellationToken) | public Task StopAsync(CancellationToken cancellationToken) | ||||
{ | { | ||||
try | try | ||||