@@ -18,12 +18,6 @@ | |||
[基于Udp管理会话服务](#udp_session) | |||
## 4.消息包计数服务 | |||
[基于Tcp消息包计数服务](#tcp_counter) | |||
[基于Udp消息包计数服务](#udp_counter) | |||
## 接口请求对照表 | |||
### 公共接口请求 | |||
@@ -39,7 +33,6 @@ | |||
| 127.0.0.1:828/jt808api/Tcp/Session/GetAll| GET| 基于Tcp管理会话服务-获取会话集合| | |||
| 127.0.0.1:828/jt808api/Tcp/Session/QueryTcpSessionByTerminalPhoneNo| POST| 基于Tcp管理会话服务-通过设备终端号查询对应会话| | |||
| 127.0.0.1:828/jt808api/Tcp/Session/RemoveByTerminalPhoneNo| POST| 基于Tcp管理会话服务-通过设备终端号移除对应会话| | |||
| 127.0.0.1:828/jt808api/Tcp/GetAtomicCounter| GET| 基于Tcp消息包计数服务| | |||
### 基于Udp接口请求 | |||
@@ -47,7 +40,6 @@ | |||
|:------|:------|:------| | |||
| 127.0.0.1:828/jt808api/Udp/Session/GetAll| GET| 基于Udp管理会话服务-获取会话集合| | |||
| 127.0.0.1:828/jt808api/Udp/Session/RemoveByTerminalPhoneNo| POST| 基于Udp管理会话服务-通过设备终端号移除对应会话| | |||
| 127.0.0.1:828/jt808api/Udp/GetAtomicCounter| GET| 基于Udp消息包计数服务| | |||
### 统一对象返回 JT808ResultDto\<T> | |||
@@ -240,55 +232,3 @@ | |||
"Data":true | |||
} | |||
``` | |||
### <span id="tcp_counter">基于Tcp消息包计数服务</span> | |||
请求地址:Tcp/GetAtomicCounter | |||
请求方式:GET | |||
返回数据: | |||
|属性|数据类型|参数说明| | |||
|------|:------:|:------| | |||
| MsgSuccessCount| long| 消息包成功数| | |||
| MsgFailCount| long| 消息包失败数| | |||
返回结果: | |||
``` counter | |||
{ | |||
"Message":"", | |||
"Code":200, | |||
"Data":{ | |||
"MsgSuccessCount":10000, | |||
"MsgFailCount":0 | |||
} | |||
} | |||
``` | |||
### <span id="udp_counter">基于Udp消息包计数服务</span> | |||
请求地址:Udp/GetAtomicCounter | |||
请求方式:GET | |||
返回数据: | |||
|属性|数据类型|参数说明| | |||
|------|:------:|:------| | |||
| MsgSuccessCount| long| 消息包成功数| | |||
| MsgFailCount| long| 消息包失败数| | |||
返回结果: | |||
``` counter | |||
{ | |||
"Message":"", | |||
"Code":200, | |||
"Data":{ | |||
"MsgSuccessCount":1000, | |||
"MsgFailCount":0 | |||
} | |||
} | |||
``` |
@@ -53,20 +53,21 @@ namespace JT808.Gateway.NormalHosting | |||
//// options.UdpPort = 808; | |||
////}) | |||
.AddNormalGateway(hostContext.Configuration) | |||
.ReplaceNormalReplyMessageHandler<JT808NormalReplyMessageHandlerImpl>() | |||
.AddMsgLogging<JT808MsgLogging>() | |||
.AddTraffic() | |||
.AddSessionNotice() | |||
.AddTransmit(hostContext.Configuration) | |||
//.ReplaceNormalReplyMessageHandler<JT808NormalReplyMessageHandlerImpl>() | |||
//.AddMsgLogging<JT808MsgLogging>() | |||
//.AddTraffic() | |||
//.AddSessionNotice() | |||
//.AddTransmit(hostContext.Configuration) | |||
.AddTcp() | |||
.AddUdp() | |||
//.AddUdp() | |||
.AddHttp() | |||
; | |||
//流量统计 | |||
services.AddHostedService<TrafficJob>(); | |||
//services.AddHostedService<TrafficJob>(); | |||
//grpc客户端调用 | |||
//services.AddHostedService<CallGrpcClientJob>(); | |||
//客户端测试 依赖AddClient()服务 | |||
services.AddHostedService<UpJob>(); | |||
//services.AddHostedService<UpJob>(); | |||
}); | |||
await serverHostBuilder.RunConsoleAsync(); | |||
@@ -7,6 +7,8 @@ | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.7" /> | |||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.7" /> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.7" /> | |||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" /> | |||
<PackageReference Include="System.IO.Pipelines" Version="4.7.2" /> | |||
@@ -22,7 +24,14 @@ | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\..\JT808.Gateway.WebApiClientTool\JT808.Gateway.WebApiClientTool.csproj" /> | |||
<ProjectReference Include="..\..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,50 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Text; | |||
using JT808.Gateway.WebApiClientTool; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Xunit; | |||
namespace JT808.Gateway.Test | |||
{ | |||
public class JT808HttpClientTest | |||
{ | |||
[Fact(DisplayName="客户端DI测试配置文件1")] | |||
public void Test() | |||
{ | |||
IServiceCollection serviceDescriptors = new ServiceCollection(); | |||
serviceDescriptors.AddJT808WebApiClientTool(new Uri("http://localhost/"), "123456"); | |||
} | |||
[Fact(DisplayName = "客户端DI测试配置文件2")] | |||
public void Test1() | |||
{ | |||
var builder = new ConfigurationBuilder(); | |||
builder.AddJsonFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appsettings.json")); | |||
IServiceCollection serviceDescriptors = new ServiceCollection(); | |||
var configuration = builder.Build(); | |||
var token = configuration.GetSection("JT808WebApiClientToolConfig:Token").Get<string>(); | |||
var uri = configuration.GetSection("JT808WebApiClientToolConfig:Uri").Get<string>(); | |||
Assert.Equal("123456", token); | |||
Assert.Equal("http://localhost/", uri); | |||
serviceDescriptors.AddJT808WebApiClientTool(builder.Build()); | |||
} | |||
[Fact(DisplayName = "使用postman测试")] | |||
public void Test2() | |||
{ | |||
//头部添加或者url参数带有token=123456 | |||
//TCP | |||
//http://127.0.0.1:828/jt808api/Tcp/Session/GetAll | |||
//http://127.0.0.1:828/jt808api/Tcp/Session/QueryTcpSessionByTerminalPhoneNo | |||
//123456789 | |||
//http://127.0.0.1:828/jt808api/Tcp/Session/RemoveByTerminalPhoneNo | |||
//123456789 | |||
///http://127.0.0.1:828/jt808api/UnificationSend | |||
//{"TerminalPhoneNo":"123456789","Data":"7e 01 02 7e"} | |||
//{"TerminalPhoneNo":"123456789","Data":"7e01027e"} | |||
} | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
{ | |||
"JT808WebApiClientToolConfig": { | |||
"Token": "123456", | |||
"Uri": "http://localhost/" | |||
} | |||
} |
@@ -22,6 +22,9 @@ | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||
<DocumentationFile>JT808.Gateway.WebApiClientTool.xml</DocumentationFile> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | |||
<DocumentationFile>JT808.Gateway.WebApiClientTool.xml</DocumentationFile> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||
</ItemGroup> | |||
@@ -0,0 +1,34 @@ | |||
<?xml version="1.0"?> | |||
<doc> | |||
<assembly> | |||
<name>JT808.Gateway.WebApiClientTool</name> | |||
</assembly> | |||
<members> | |||
<member name="M:JT808.Gateway.WebApiClientTool.JT808HttpClient.GetTcpSessionAll"> | |||
<summary> | |||
会话服务集合 | |||
</summary> | |||
<returns></returns> | |||
</member> | |||
<member name="M:JT808.Gateway.WebApiClientTool.JT808HttpClient.RemoveByTerminalPhoneNo(System.String)"> | |||
<summary> | |||
会话服务-通过设备终端号移除对应会话 | |||
</summary> | |||
<param name="terminalPhoneNo"></param> | |||
<returns></returns> | |||
</member> | |||
<member name="M:JT808.Gateway.WebApiClientTool.JT808HttpClient.UnificationSend(JT808.Gateway.Abstractions.Dtos.JT808UnificationSendRequestDto)"> | |||
<summary> | |||
统一下发信息 | |||
</summary> | |||
<param name="jT808UnificationSendRequestDto"></param> | |||
<returns></returns> | |||
</member> | |||
<member name="M:JT808.Gateway.WebApiClientTool.JT808HttpClient.GetUdpSessionAll"> | |||
<summary> | |||
会话服务集合 | |||
</summary> | |||
<returns></returns> | |||
</member> | |||
</members> | |||
</doc> |
@@ -25,7 +25,7 @@ namespace JT808.Gateway.WebApiClientTool | |||
public async ValueTask<JT808ResultDto<List<JT808TcpSessionInfoDto>>> GetTcpSessionAll() | |||
{ | |||
var request = new HttpRequestMessage(HttpMethod.Get, JT808GatewayConstants.JT808WebApiRouteTable.SessionTcpGetAll); | |||
var response = HttpClient.SendAsync(request).Result; | |||
var response = await HttpClient.SendAsync(request); | |||
response.EnsureSuccessStatusCode(); | |||
var data = await response.Content.ReadAsStreamAsync(); | |||
var value = await JsonSerializer.DeserializeAsync<JT808ResultDto<List<JT808TcpSessionInfoDto>>>(data); | |||
@@ -41,7 +41,7 @@ namespace JT808.Gateway.WebApiClientTool | |||
{ | |||
var request = new HttpRequestMessage(HttpMethod.Post, JT808GatewayConstants.JT808WebApiRouteTable.SessionRemoveByTerminalPhoneNo); | |||
request.Content = new StringContent(terminalPhoneNo); | |||
var response = HttpClient.SendAsync(request).Result; | |||
var response = await HttpClient.SendAsync(request); | |||
response.EnsureSuccessStatusCode(); | |||
var data = await response.Content.ReadAsStreamAsync(); | |||
var value = await JsonSerializer.DeserializeAsync<JT808ResultDto<bool>>(data); | |||
@@ -57,7 +57,7 @@ namespace JT808.Gateway.WebApiClientTool | |||
{ | |||
var request = new HttpRequestMessage(HttpMethod.Post, JT808GatewayConstants.JT808WebApiRouteTable.UnificationSend); | |||
request.Content = new StringContent(JsonSerializer.Serialize(jT808UnificationSendRequestDto)); | |||
var response = HttpClient.SendAsync(request).Result; | |||
var response = await HttpClient.SendAsync(request); | |||
response.EnsureSuccessStatusCode(); | |||
var data = await response.Content.ReadAsStreamAsync(); | |||
var value = await JsonSerializer.DeserializeAsync<JT808ResultDto<bool>>(data); | |||
@@ -71,7 +71,7 @@ namespace JT808.Gateway.WebApiClientTool | |||
public async ValueTask<JT808ResultDto<List<JT808UdpSessionInfoDto>>> GetUdpSessionAll() | |||
{ | |||
var request = new HttpRequestMessage(HttpMethod.Get, JT808GatewayConstants.JT808WebApiRouteTable.SessionUdpGetAll); | |||
var response = HttpClient.SendAsync(request).Result; | |||
var response = await HttpClient.SendAsync(request); | |||
response.EnsureSuccessStatusCode(); | |||
var data = await response.Content.ReadAsStreamAsync(); | |||
var value = await JsonSerializer.DeserializeAsync<JT808ResultDto<List<JT808UdpSessionInfoDto>>>(data); | |||
@@ -8,10 +8,11 @@ namespace JT808.Gateway.WebApiClientTool | |||
{ | |||
public static class JT808HttpClientExtensions | |||
{ | |||
public static IServiceCollection AddJT808WebApiClientTool(this IServiceCollection serviceDescriptors, Uri webapiUri) | |||
public static IServiceCollection AddJT808WebApiClientTool(this IServiceCollection serviceDescriptors, Uri webapiUri,string token) | |||
{ | |||
serviceDescriptors.AddHttpClient("JT808WebApiClientTool", c => | |||
{ | |||
c.DefaultRequestHeaders.Add("token", token); | |||
c.BaseAddress = webapiUri; | |||
c.Timeout = TimeSpan.FromSeconds(3); | |||
}) | |||
@@ -23,7 +24,8 @@ namespace JT808.Gateway.WebApiClientTool | |||
{ | |||
serviceDescriptors.AddHttpClient("JT808WebApiClientTool", c => | |||
{ | |||
c.BaseAddress = new Uri(configuration.GetSection("JT808WebApiClientToolConfig").Get<string>()); | |||
c.DefaultRequestHeaders.Add("token", configuration.GetSection("JT808WebApiClientToolConfig:Token").Get<string>()); | |||
c.BaseAddress = new Uri(configuration.GetSection("JT808WebApiClientToolConfig:Uri").Get<string>()); | |||
c.Timeout = TimeSpan.FromSeconds(3); | |||
}) | |||
.AddTypedClient<JT808HttpClient>(); | |||
@@ -0,0 +1,48 @@ | |||
using JT808.Gateway.Abstractions; | |||
using JT808.Gateway.Configurations; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Security.Claims; | |||
using System.Security.Principal; | |||
using System.Text; | |||
namespace JT808.Gateway.Authorization | |||
{ | |||
class JT808AuthorizationDefault : IJT808Authorization | |||
{ | |||
private IOptionsMonitor<JT808Configuration> optionsMonitor; | |||
public JT808AuthorizationDefault(IOptionsMonitor<JT808Configuration> optionsMonitor) | |||
{ | |||
this.optionsMonitor = optionsMonitor; | |||
} | |||
public bool Authorization(HttpListenerContext context, out IPrincipal principal) | |||
{ | |||
var uriSpan = context.Request.Url.AbsoluteUri.AsSpan(); | |||
var uriParamStr = uriSpan.Slice(uriSpan.IndexOf('?')+1).ToString().ToLower(); | |||
var uriParams = uriParamStr.Split('&'); | |||
var tokenParam = uriParams.FirstOrDefault(m => m.Contains("token")); | |||
string tokenValue = string.Empty; | |||
if (!string.IsNullOrEmpty(tokenParam)) | |||
{ | |||
tokenValue = tokenParam.Split('=')[1]; | |||
} | |||
else | |||
{ | |||
tokenValue = context.Request.Headers.Get("token"); | |||
} | |||
if (optionsMonitor.CurrentValue.WebApiToken == tokenValue) | |||
{ | |||
principal = new ClaimsPrincipal(new GenericIdentity(tokenValue)); | |||
return true; | |||
} | |||
else | |||
{ | |||
principal = null; | |||
return false; | |||
} | |||
} | |||
} | |||
} |
@@ -46,6 +46,15 @@ namespace JT808.Gateway.Extensions | |||
context.Response.Close(); | |||
} | |||
public static void Http405(this HttpListenerContext context) | |||
{ | |||
context.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed; | |||
context.Response.KeepAlive = false; | |||
context.Response.ContentType = jsonType; | |||
context.Response.OutputStream.Close(); | |||
context.Response.Close(); | |||
} | |||
public static async ValueTask Http500(this HttpListenerContext context) | |||
{ | |||
byte[] b = Encoding.UTF8.GetBytes("inner error"); | |||
@@ -1,4 +1,5 @@ | |||
using JT808.Gateway.Abstractions; | |||
using JT808.Gateway.Authorization; | |||
using JT808.Gateway.Configurations; | |||
using JT808.Gateway.Enums; | |||
using JT808.Gateway.Handlers; | |||
@@ -77,6 +78,7 @@ namespace JT808.Gateway | |||
public static IJT808GatewayBuilder AddHttp(this IJT808GatewayBuilder config) | |||
{ | |||
config.JT808Builder.Services.AddSingleton<IJT808Authorization, JT808AuthorizationDefault>(); | |||
config.JT808Builder.Services.AddSingleton<JT808MsgIdDefaultWebApiHandler>(); | |||
config.JT808Builder.Services.AddHostedService<JT808HttpServer>(); | |||
return config; | |||
@@ -85,6 +87,7 @@ namespace JT808.Gateway | |||
public static IJT808GatewayBuilder AddHttp<TJT808MsgIdDefaultWebApiHandler>(this IJT808GatewayBuilder config) | |||
where TJT808MsgIdDefaultWebApiHandler: JT808MsgIdDefaultWebApiHandler | |||
{ | |||
config.JT808Builder.Services.AddSingleton<IJT808Authorization, JT808AuthorizationDefault>(); | |||
config.JT808Builder.Services.AddSingleton(typeof(JT808MsgIdDefaultWebApiHandler),typeof(TJT808MsgIdDefaultWebApiHandler)); | |||
config.JT808Builder.Services.AddHostedService<JT808HttpServer>(); | |||
return config; | |||
@@ -10,7 +10,9 @@ using System; | |||
using System.Buffers; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Net.Http; | |||
using System.Net.WebSockets; | |||
using System.Security.Principal; | |||
using System.Text; | |||
@@ -62,14 +64,19 @@ namespace JT808.Gateway | |||
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}."); | |||
Task.Factory.StartNew(async() => | |||
Task.Factory.StartNew(async () => | |||
{ | |||
while (listener.IsListening) | |||
{ | |||
var context = await listener.GetContextAsync(); | |||
try | |||
{ | |||
if (authorization.Authorization(context,out var principal)) | |||
if (context.Request.RawUrl.StartsWith("/favicon.ico")) | |||
{ | |||
context.Http404(); | |||
continue; | |||
} | |||
if (authorization.Authorization(context, out var principal)) | |||
{ | |||
await ProcessRequestAsync(context, principal); | |||
} | |||
@@ -90,18 +97,37 @@ namespace JT808.Gateway | |||
private async ValueTask ProcessRequestAsync(HttpListenerContext context, IPrincipal principal) | |||
{ | |||
if(context.Request.RawUrl.StartsWith("/favicon.ico")) | |||
var router = MsgIdDefaultWebApiHandler.HandlerDict.FirstOrDefault(f => context.Request.RawUrl.StartsWith(f.Key)); | |||
if (router.Key == null) | |||
{ | |||
context.Http404(); | |||
return; | |||
} | |||
var uri = new Uri(context.Request.RawUrl); | |||
//todo: 处理对应的handler | |||
string url = uri.AbsolutePath; | |||
var queryParams = uri.Query.Substring(1, uri.Query.Length - 1).Split('&'); | |||
if (queryParams.Length < 2) { | |||
context.Http404(); | |||
return; | |||
if(context.Request.HttpMethod == HttpMethod.Get.Method) | |||
{ | |||
var index = context.Request.Url.AbsoluteUri.IndexOf('?'); | |||
if (index > 0) | |||
{ | |||
var uriParamStr = context.Request.Url.AbsoluteUri.Substring(index + 1).ToString(); | |||
await context.HttpSend(router.Value(uriParamStr)); | |||
} | |||
else | |||
{ | |||
await context.HttpSend(router.Value("")); | |||
} | |||
} | |||
else if(context.Request.HttpMethod == HttpMethod.Post.Method) | |||
{ | |||
string json = string.Empty; | |||
using (var reader = new StreamReader(context.Request.InputStream,context.Request.ContentEncoding)) | |||
{ | |||
json = reader.ReadToEnd(); | |||
} | |||
await context.HttpSend(router.Value(json)); | |||
} | |||
else | |||
{ | |||
context.Http405(); | |||
} | |||
} | |||