@@ -36,6 +36,6 @@ jobs: | |||||
- name: dotnet JT808.Gateway restore | - name: dotnet JT808.Gateway restore | ||||
run: dotnet restore ./src/JT808.Gateway.sln | run: dotnet restore ./src/JT808.Gateway.sln | ||||
- name: dotnet JT808.Gateway build | - name: dotnet JT808.Gateway build | ||||
run: dotnet build ./src/JT808.Gateway.Test/JT808.Gateway.Test.csproj | |||||
run: dotnet build ./src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj | |||||
- name: dotnet JT808.Gateway test | - name: dotnet JT808.Gateway test | ||||
run: dotnet test ./src/JT808.Gateway.Test/JT808.Gateway.Test.csproj | |||||
run: dotnet test ./src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj |
@@ -12,9 +12,9 @@ | |||||
[了解JTNE协议进这边](https://github.com/SmallChi/JTNewEnergy) | [了解JTNE协议进这边](https://github.com/SmallChi/JTNewEnergy) | ||||
[玩一玩压力测试](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/README.md) | |||||
[玩一玩压力测试](https://github.com/SmallChi/JT808Gateway/blob/master/doc/README.md) | |||||
[](https://github.com/SmallChi/JT808DotNetty/blob/master/LICENSE)[]() | |||||
[](https://github.com/SmallChi/JT808Gateway/blob/master/LICENSE)[]() | |||||
## 新网关的优势 | ## 新网关的优势 | ||||
@@ -25,7 +25,7 @@ | |||||
## 设计模型 | ## 设计模型 | ||||
 | |||||
 | |||||
## 集成接口功能 | ## 集成接口功能 | ||||
@@ -85,8 +85,9 @@ | |||||
| --------------------- | -------------------------------------------------- | --------------------------------------------------- | | | --------------------- | -------------------------------------------------- | --------------------------------------------------- | | ||||
| Install-Package JT808.Gateway.Abstractions|  |  | | | Install-Package JT808.Gateway.Abstractions|  |  | | ||||
| Install-Package JT808.Gateway |  |  | | | Install-Package JT808.Gateway |  |  | | ||||
| Install-Package JT808.Gateway.Kafka|  |  | | |||||
| Install-Package JT808.Gateway.Client|  |  | | |||||
| Install-Package JT808.Gateway.InMemoryMQ|  |  | | | Install-Package JT808.Gateway.InMemoryMQ|  |  | | ||||
| Install-Package JT808.Gateway.Kafka|  |  | | |||||
| Install-Package JT808.Gateway.Transmit |  |  | | | Install-Package JT808.Gateway.Transmit |  |  | | ||||
| Install-Package JT808.Gateway.Traffic |  | | | | Install-Package JT808.Gateway.Traffic |  | | | ||||
| Install-Package JT808.Gateway.SessionNotice |  | | | | Install-Package JT808.Gateway.SessionNotice |  | | | ||||
@@ -94,106 +95,7 @@ | |||||
| Install-Package JT808.Gateway.MsgLogging |  | | | | Install-Package JT808.Gateway.MsgLogging |  | | | ||||
| Install-Package JT808.Gateway.MsgIdHandler |  | | | | Install-Package JT808.Gateway.MsgIdHandler |  | | | ||||
## 举个栗子1 | |||||
``` demo1 | |||||
static async Task Main(string[] args) | |||||
{ | |||||
var serverHostBuilder = new HostBuilder() | |||||
.ConfigureAppConfiguration((hostingContext, config) => | |||||
{ | |||||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); | |||||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); | |||||
}) | |||||
.ConfigureLogging((context, logging) => | |||||
{ | |||||
logging.AddConsole(); | |||||
logging.SetMinimumLevel(LogLevel.Trace); | |||||
}) | |||||
.ConfigureServices((hostContext, services) => | |||||
{ | |||||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||||
services.AddJT808Configure() | |||||
.AddJT808NettyCore(hostContext.Configuration) | |||||
.AddJT808TcpNettyHost() | |||||
.AddJT808UdpNettyHost() | |||||
.AddJT808WebApiNettyHost() | |||||
//扩展webapi JT808MsgIdHttpHandlerBase | |||||
//.ReplaceMsgIdHandler<JT808MsgIdHttpCustomHandler>() | |||||
.Builder(); | |||||
//添加kafka插件 | |||||
//.AddJT808ServerKafkaMsgProducer(hostContext.Configuration) | |||||
//.AddJT808ServerKafkaMsgReplyConsumer(hostContext.Configuration) | |||||
//.AddJT808ServerKafkaSessionProducer(hostContext.Configuration) | |||||
//.Builder(); | |||||
//使用微软自带的webapi客户端 | |||||
//services.AddHttpClient("jt808webapi", c => | |||||
//{ | |||||
// c.BaseAddress = new Uri("http://localhost:828/"); | |||||
// c.DefaultRequestHeaders.Add("token", "123456); | |||||
//}) | |||||
//.AddTypedClient<JT808HttpClient>(); | |||||
//var client = services.BuildServiceProvider().GetRequiredService<JT808HttpClient>(); | |||||
//var result = client.GetTcpAtomicCounter(); | |||||
}); | |||||
await serverHostBuilder.RunConsoleAsync(); | |||||
} | |||||
``` | |||||
如图所示: | |||||
 | |||||
## 举个栗子2 | |||||
``` 1 | |||||
static async Task Main(string[] args) | |||||
{ | |||||
var serverHostBuilder = new HostBuilder() | |||||
.ConfigureAppConfiguration((hostingContext, config) => | |||||
{ | |||||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory) | |||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | |||||
.AddJsonFile($"appsettings.{ hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); | |||||
}) | |||||
.ConfigureLogging((context, logging) => | |||||
{ | |||||
Console.WriteLine($"Environment.OSVersion.Platform:{Environment.OSVersion.Platform.ToString()}"); | |||||
NLog.LogManager.LoadConfiguration($"Configs/nlog.{Environment.OSVersion.Platform.ToString()}.config"); | |||||
logging.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true }); | |||||
logging.SetMinimumLevel(LogLevel.Trace); | |||||
}) | |||||
.ConfigureServices((hostContext, services) => | |||||
{ | |||||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||||
services.AddJT808Configure() | |||||
//.AddJT808Gateway(options => | |||||
//{ | |||||
// options.TcpPort = 808; | |||||
// options.UdpPort = 808; | |||||
//}) | |||||
.AddJT808Gateway(hostContext.Configuration) | |||||
.AddTcp() | |||||
.AddUdp() | |||||
.AddGrpc() | |||||
//InMemoryMQ | |||||
.AddJT808ServerInMemoryMQ() | |||||
.AddJT808InMemoryReplyMessage() | |||||
//kafka插件 | |||||
//.AddJT808ServerKafkaMsgProducer(hostContext.Configuration) | |||||
//.AddJT808ServerKafkaMsgReplyConsumer(hostContext.Configuration) | |||||
//.AddJT808ServerKafkaSessionProducer(hostContext.Configuration) | |||||
; | |||||
//services.AddHostedService<CallGrpcClientJob>(); | |||||
}); | |||||
await serverHostBuilder.RunConsoleAsync(); | |||||
} | |||||
``` | |||||
## 举个栗子3 | |||||
## 举个栗子 | |||||
1.打开项目进行还原编译生成 | 1.打开项目进行还原编译生成 | ||||
@@ -202,4 +104,4 @@ static async Task Main(string[] args) | |||||
3.进入JT808.DotNetty.SimpleClient项目下的Debug目录运行客户端 | 3.进入JT808.DotNetty.SimpleClient项目下的Debug目录运行客户端 | ||||
如图所示: | 如图所示: | ||||
 | |||||
 |
@@ -1,31 +1,15 @@ | |||||
# 压力测试 | # 压力测试 | ||||
## 基于DotNetty | |||||
[感谢泥水佬提供的压力测试工具](https://www.cnblogs.com/smark/p/4496660.html?utm_source=tuicool) | |||||
| 操作系统 | 配置 | 使用 | | |||||
|:-------:|:-------:|:-------:| | |||||
| win server 2016 | 4c8g | 压力测试客户端 | | |||||
| centos7 | 4c8g | JT808服务端 | | |||||
 | |||||
 | |||||
 | |||||
 | |||||
## 基于pipeline | ## 基于pipeline | ||||
**由于【参数配置】不同导致测试的效果可能不同,只是谁便测试玩玩,反正机器便宜。** | |||||
**只是谁便测试玩玩,反正机器便宜。** | |||||
> 注意1:连接数和并发数要区分开; | > 注意1:连接数和并发数要区分开; | ||||
> 注意2:阿里云的机器默认有连接数限制(5000),可以先创建一台,把该装的软件安装好,tcp参数内核调优后,在备份一个系统镜像在玩。 | |||||
> 注意2:阿里云的机器默认有连接数限制(5000),可以先创建一台,把该装的软件安装好,tcp参数内核调优后,在备份一个系统镜像在玩; | |||||
> 注意3: 使用的是内存队列(InMemoryMQ)进行测试。 | |||||
``` 1 | ``` 1 | ||||
使用PM2托管 | |||||
//使用PM2托管 | |||||
//服务端 | //服务端 | ||||
cd /data/JT808.Gateway | cd /data/JT808.Gateway | ||||
@@ -35,6 +19,7 @@ pm2 start "dotnet JT808.Gateway.TestHosting.dll ASPNETCORE_ENVIRONMENT=Productio | |||||
cd /data/JT808Client | cd /data/JT808Client | ||||
pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Production" --max-restarts=1 -n "JT808.Gateway.CleintBenchmark" -o "/data/pm2Logs/JT808.Gateway.CleintBenchmark/out.log" -e "/data/pm2Logs/JT808.Gateway.CleintBenchmark/error.log" | pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Production" --max-restarts=1 -n "JT808.Gateway.CleintBenchmark" -o "/data/pm2Logs/JT808.Gateway.CleintBenchmark/out.log" -e "/data/pm2Logs/JT808.Gateway.CleintBenchmark/error.log" | ||||
//可选的 | |||||
修改wwwroot下index.html的webapi接口地址 | 修改wwwroot下index.html的webapi接口地址 | ||||
127.0.0.1:15004/index.html | 127.0.0.1:15004/index.html | ||||
``` | ``` | ||||
@@ -55,11 +40,22 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||||
"IP": "", | "IP": "", | ||||
"Port": 808, | "Port": 808, | ||||
"DeviceCount": 10000, | "DeviceCount": 10000, | ||||
"Interval": 10, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | "DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | ||||
} | } | ||||
``` | ``` | ||||
服务器参数配置appsettings.json | |||||
``` 1 | |||||
"JT808Configuration": { | |||||
"TcpPort": 808, | |||||
"UdpPort": 808, | |||||
"MiniNumBufferSize": 80960, | |||||
"SoBacklog": 102400 | |||||
} | |||||
``` | |||||
 |  | ||||
 |  | ||||
@@ -82,18 +78,29 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||||
"IP": "", | "IP": "", | ||||
"Port": 808, | "Port": 808, | ||||
"DeviceCount": 20000, | "DeviceCount": 20000, | ||||
"Interval": 300, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | "DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | ||||
} | } | ||||
``` | ``` | ||||
服务器参数配置appsettings.json | |||||
``` 1 | |||||
"JT808Configuration": { | |||||
"TcpPort": 808, | |||||
"UdpPort": 808, | |||||
"MiniNumBufferSize": 80960, | |||||
"SoBacklog": 102400 | |||||
} | |||||
``` | |||||
 |  | ||||
 |  | ||||
 |  | ||||
### 40K | |||||
### 30K | |||||
| 操作系统 | 配置 | 使用 | | | 操作系统 | 配置 | 使用 | | ||||
|:-------:|:-------:|:-------:| | |:-------:|:-------:|:-------:| | ||||
@@ -108,39 +115,130 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||||
"ClientBenchmarkOptions": { | "ClientBenchmarkOptions": { | ||||
"IP": "", | "IP": "", | ||||
"Port": 808, | "Port": 808, | ||||
"DeviceCount": 40000, | |||||
"DeviceCount": 30000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||||
} | |||||
``` | |||||
服务器参数配置appsettings.json | |||||
``` 1 | |||||
"JT808Configuration": { | |||||
"TcpPort": 808, | |||||
"UdpPort": 808, | |||||
"MiniNumBufferSize": 80960, | |||||
"SoBacklog": 102400 | |||||
} | |||||
``` | |||||
 | |||||
 | |||||
 | |||||
### 40K | |||||
| 操作系统 | 配置 | 使用 | | |||||
|:-------:|:-------:|:-------:| | |||||
| centos7 | 8c16g | JT808服务端 | | |||||
| centos7 | 8c16g | JT808客户端 | | |||||
> 计算网络增强型 sn1ne ecs.sn1ne.2xlarge 8 vCPU 16 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2 Gbps 100 万 PPS | |||||
客户端1参数配置appsettings.json | |||||
``` 1 | |||||
"urls": "http://*:15004;", | |||||
"ClientBenchmarkOptions": { | |||||
"IP": "", | |||||
"Port": 808, | |||||
"DeviceCount": 20000, | |||||
"Interval": 1000, | "Interval": 1000, | ||||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | "DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | ||||
} | } | ||||
修改wwwroot下index.html的webapi接口地址 | |||||
127.0.0.1:15004/index.html | |||||
``` | |||||
``` 2 | |||||
"urls": "http://*:15005;", | |||||
"ClientBenchmarkOptions": { | |||||
"IP": "", | |||||
"Port": 808, | |||||
"DeviceCount": 20000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 200000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||||
} | |||||
修改wwwroot下index.html的webapi接口地址 | |||||
127.0.0.1:15005/index.html | |||||
``` | |||||
> 一个进程的线程是有限的,所以分两个进程进行测试 | |||||
服务器参数配置appsettings.json | |||||
``` 1 | |||||
"JT808Configuration": { | |||||
"TcpPort": 808, | |||||
"UdpPort": 808, | |||||
"MiniNumBufferSize": 80960, | |||||
"SoBacklog": 102400 | |||||
} | |||||
``` | ``` | ||||
 |  | ||||
 |  | ||||
 | |||||
> 由于资源被占满了,所以客户端的界面访问不到,但是不影响总体。 | |||||
### 60K | ### 60K | ||||
| 操作系统 | 配置 | 使用 | | | 操作系统 | 配置 | 使用 | | ||||
|:-------:|:-------:|:-------:| | |:-------:|:-------:|:-------:| | ||||
| centos7 | 8c16g | JT808服务端 | | | centos7 | 8c16g | JT808服务端 | | ||||
| centos7 | 8c16g | JT808客户端 | | |||||
| centos7 | 8c16g | JT808客户端1 | | |||||
| centos7 | 8c16g | JT808客户端2 | | |||||
> 计算网络增强型 sn1ne ecs.sn1ne.2xlarge 8 vCPU 16 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2 Gbps 100 万 PPS | > 计算网络增强型 sn1ne ecs.sn1ne.2xlarge 8 vCPU 16 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2 Gbps 100 万 PPS | ||||
客户端参数配置appsettings.json | |||||
客户端1参数配置appsettings.json | |||||
``` 1 | ``` 1 | ||||
"ClientBenchmarkOptions": { | "ClientBenchmarkOptions": { | ||||
"IP": "", | "IP": "", | ||||
"Port": 808, | "Port": 808, | ||||
"DeviceCount": 60000, | |||||
"DeviceCount": 30000, | |||||
"Interval": 1000, | "Interval": 1000, | ||||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | "DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | ||||
} | } | ||||
``` | ``` | ||||
客户端2参数配置appsettings.json | |||||
``` 2 | |||||
"ClientBenchmarkOptions": { | |||||
"IP": "", | |||||
"Port": 808, | |||||
"DeviceCount": 30000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 200000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||||
} | |||||
``` | |||||
服务器参数配置appsettings.json | |||||
``` 1 | |||||
"JT808Configuration": { | |||||
"TcpPort": 808, | |||||
"UdpPort": 808, | |||||
"MiniNumBufferSize": 102400, | |||||
"SoBacklog": 102400 | |||||
} | |||||
``` | |||||
 |  | ||||
 |  | ||||
@@ -151,10 +249,13 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||||
| 操作系统 | 配置 | 使用 | | | 操作系统 | 配置 | 使用 | | ||||
|:-------:|:-------:|:-------:| | |:-------:|:-------:|:-------:| | ||||
| centos7 | 8c16g | JT808服务端 | | |||||
| centos7 | 16c24g | JT808服务端 | | |||||
| centos7 | 8c16g | JT808客户端 | | |||||
| centos7 | 8c16g | JT808客户端 | | |||||
| centos7 | 8c16g | JT808客户端 | | | centos7 | 8c16g | JT808客户端 | | ||||
| centos7 | 8c16g | JT808客户端 | | | centos7 | 8c16g | JT808客户端 | | ||||
> 计算网络增强型 sn1ne ecs.sn1ne.3xlarge 12 vCPU 24 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2.5 Gbps 130 万 PPS | |||||
> 计算网络增强型 sn1ne ecs.sn1ne.2xlarge 8 vCPU 16 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2 Gbps 100 万 PPS | > 计算网络增强型 sn1ne ecs.sn1ne.2xlarge 8 vCPU 16 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2 Gbps 100 万 PPS | ||||
客户端1的参数配置appsettings.json | 客户端1的参数配置appsettings.json | ||||
@@ -163,8 +264,8 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||||
"ClientBenchmarkOptions": { | "ClientBenchmarkOptions": { | ||||
"IP": "", | "IP": "", | ||||
"Port": 808, | "Port": 808, | ||||
"DeviceCount": 40000, | |||||
"Interval": 3000, | |||||
"DeviceCount": 20000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | "DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | ||||
} | } | ||||
``` | ``` | ||||
@@ -175,14 +276,196 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||||
"ClientBenchmarkOptions": { | "ClientBenchmarkOptions": { | ||||
"IP": "", | "IP": "", | ||||
"Port": 808, | "Port": 808, | ||||
"DeviceCount": 40000, | |||||
"Interval": 3000, | |||||
"DeviceCount": 20000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 200000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | "DeviceTemplate": 200000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | ||||
} | } | ||||
``` | ``` | ||||
客户端3的参数配置appsettings.json | |||||
``` 3 | |||||
"ClientBenchmarkOptions": { | |||||
"IP": "", | |||||
"Port": 808, | |||||
"DeviceCount": 20000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 300000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||||
} | |||||
``` | |||||
客户端3的参数配置appsettings.json | |||||
``` 4 | |||||
"ClientBenchmarkOptions": { | |||||
"IP": "", | |||||
"Port": 808, | |||||
"DeviceCount": 20000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 400000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||||
} | |||||
``` | |||||
服务器参数配置appsettings.json | |||||
``` 1 | |||||
"JT808Configuration": { | |||||
"TcpPort": 808, | |||||
"UdpPort": 808, | |||||
"MiniNumBufferSize": 204800, | |||||
"SoBacklog": 204800 | |||||
} | |||||
``` | |||||
 |  | ||||
 |  | ||||
 | |||||
### 100K | |||||
| 操作系统 | 配置 | 使用 | | |||||
|:-------:|:-------:|:-------:| | |||||
| centos7 | 16c24g | JT808服务端 | | |||||
| centos7 | 8c16g | JT808客户端 | | |||||
| centos7 | 8c16g | JT808客户端 | | |||||
| centos7 | 8c16g | JT808客户端 | | |||||
| centos7 | 8c16g | JT808客户端 | | |||||
> 计算网络增强型 sn1ne ecs.sn1ne.3xlarge 12 vCPU 24 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2.5 Gbps 130 万 PPS | |||||
> 计算网络增强型 sn1ne ecs.sn1ne.2xlarge 8 vCPU 16 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2 Gbps 100 万 PPS | |||||
客户端1的参数配置appsettings.json | |||||
``` 1 | |||||
"ClientBenchmarkOptions": { | |||||
"IP": "", | |||||
"Port": 808, | |||||
"DeviceCount": 25000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||||
} | |||||
``` | |||||
客户端2的参数配置appsettings.json | |||||
``` 2 | |||||
"ClientBenchmarkOptions": { | |||||
"IP": "", | |||||
"Port": 808, | |||||
"DeviceCount": 25000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 200000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||||
} | |||||
``` | |||||
客户端3的参数配置appsettings.json | |||||
``` 3 | |||||
"ClientBenchmarkOptions": { | |||||
"IP": "", | |||||
"Port": 808, | |||||
"DeviceCount": 25000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 300000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||||
} | |||||
``` | |||||
客户端3的参数配置appsettings.json | |||||
``` 4 | |||||
"ClientBenchmarkOptions": { | |||||
"IP": "", | |||||
"Port": 808, | |||||
"DeviceCount": 25000, | |||||
"Interval": 1000, | |||||
"DeviceTemplate": 400000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||||
} | |||||
``` | |||||
服务器参数配置appsettings.json | |||||
``` 1 | |||||
"JT808Configuration": { | |||||
"TcpPort": 808, | |||||
"UdpPort": 808, | |||||
"MiniNumBufferSize": 204800, | |||||
"SoBacklog": 204800 | |||||
} | |||||
``` | |||||
 | |||||
 | |||||
### 参考Centos7内核参数调优 | |||||
``` 99 | |||||
vi /etc/security/limits.conf | |||||
修改如下: | |||||
root soft nofile 204800 | |||||
root hard nofile 204800 | |||||
* soft nofile 204800 | |||||
* hard nofile 204800 | |||||
vi /etc/pam.d/login | |||||
添加如下: | |||||
session required pam_limits.so | |||||
vi /etc/sysctl.conf | |||||
添加如下: | |||||
vm.swappiness = 0 | |||||
net.ipv4.neigh.default.gc_stale_time = 120 | |||||
# see details in https://help.aliyun.com/knowledge_detail/39428.html | |||||
net.ipv4.conf.all.rp_filter = 0 | |||||
net.ipv4.conf.default.rp_filter = 0 | |||||
net.ipv4.conf.default.arp_announce = 2 | |||||
net.ipv4.conf.lo.arp_announce = 2 | |||||
net.ipv4.conf.all.arp_announce = 2 | |||||
# see details in https://help.aliyun.com/knowledge_detail/41334.html | |||||
net.ipv4.tcp_synack_retries = 2 | |||||
net.ipv4.tcp_syn_retries = 1 | |||||
net.ipv4.tcp_synack_retries = 1 | |||||
net.ipv4.tcp_keepalive_time = 600 | |||||
net.ipv4.tcp_keepalive_probes = 3 | |||||
net.ipv4.tcp_keepalive_intvl =15 | |||||
net.ipv4.tcp_retries2 = 5 | |||||
net.ipv4.tcp_fin_timeout = 1 | |||||
net.ipv4.tcp_max_tw_buckets = 65535 | |||||
net.ipv4.tcp_tw_recycle = 1 | |||||
net.ipv4.tcp_tw_reuse = 1 | |||||
net.ipv4.tcp_max_orphans = 32768 | |||||
net.ipv4.tcp_syncookies = 1 | |||||
net.ipv4.tcp_max_syn_backlog = 65535 | |||||
net.ipv4.tcp_wmem = 8192 131072 16777216 | |||||
net.ipv4.tcp_rmem = 32768 131072 16777216 | |||||
net.ipv4.tcp_mem = 94500000 915000000 927000000 | |||||
net.ipv4.ip_local_port_range = 1024 65000 | |||||
net.core.somaxconn = 65535 | |||||
net.core.netdev_max_backlog = 65535 | |||||
fs.file-max = 265535 | |||||
net.ipv6.conf.lo.disable_ipv6 = 1 | |||||
kernel.sysrq = 1 | |||||
net.ipv6.conf.all.disable_ipv6 = 1 | |||||
net.ipv6.conf.default.disable_ipv6 = 1 | |||||
最后重启机器下: | |||||
reboot | |||||
``` | |||||
## 基于DotNetty | |||||
[感谢泥水佬提供的压力测试工具](https://www.cnblogs.com/smark/p/4496660.html?utm_source=tuicool) | |||||
| 操作系统 | 配置 | 使用 | | |||||
|:-------:|:-------:|:-------:| | |||||
| win server 2016 | 4c8g | 压力测试客户端 | | |||||
| centos7 | 4c8g | JT808服务端 | | |||||
 | |||||
 | |||||
 | |||||
 |
@@ -1,14 +1,15 @@ | |||||
dotnet pack .\src\JT808.Gateway\JT808.Gateway.csproj --no-build --output ../../nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj --no-build --output ../../nupkgs | |||||
dotnet pack .\src\JT808.Gateway.InMemoryMQ\JT808.Gateway.InMemoryMQ.csproj --no-build --output ../../nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Abstractions\JT808.Gateway.Abstractions.csproj --no-build --output ../../nupkgs | |||||
dotnet pack .\src\JT808.Gateway\JT808.Gateway.csproj -c Release --output nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj -c Release --output nupkgs | |||||
dotnet pack .\src\JT808.Gateway.InMemoryMQ\JT808.Gateway.InMemoryMQ.csproj -c Release --output nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Abstractions\JT808.Gateway.Abstractions.csproj -c Release --output nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Client\JT808.Gateway.Client.csproj -c Release --output nupkgs | |||||
echo 'push service pacakge...' | echo 'push service pacakge...' | ||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.MsgIdHandler\JT808.Gateway.MsgIdHandler.csproj --no-build --output ../../nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.MsgLogging\JT808.Gateway.MsgLogging.csproj --no-build --output ../../nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.ReplyMessage\JT808.Gateway.ReplyMessage.csproj --no-build --output ../../nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.SessionNotice\JT808.Gateway.SessionNotice.csproj --no-build --output ../../nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.Traffic\JT808.Gateway.Traffic.csproj --no-build --output ../../nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.Transmit\JT808.Gateway.Transmit.csproj --no-build --output ../../nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.MsgIdHandler\JT808.Gateway.MsgIdHandler.csproj -c Release --output nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.MsgLogging\JT808.Gateway.MsgLogging.csproj -c Release --output nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.ReplyMessage\JT808.Gateway.ReplyMessage.csproj -c Release --output nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.SessionNotice\JT808.Gateway.SessionNotice.csproj -c Release --output nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.Traffic\JT808.Gateway.Traffic.csproj -c Release --output nupkgs | |||||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.Transmit\JT808.Gateway.Transmit.csproj -c Release --output nupkgs | |||||
pause | pause |
@@ -22,7 +22,9 @@ | |||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\JT808.Gateway.Client\JT808.Gateway.Client.csproj" /> | <ProjectReference Include="..\JT808.Gateway.Client\JT808.Gateway.Client.csproj" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | |||||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | <ItemGroup> | ||||
<None Include="wwwroot\echarts.min.js"> | <None Include="wwwroot\echarts.min.js"> | ||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
@@ -68,7 +68,7 @@ namespace JT808.Gateway.CleintBenchmark | |||||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | services.AddSingleton<ILoggerFactory, LoggerFactory>(); | ||||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | ||||
services.AddJT808Configure() | services.AddJT808Configure() | ||||
.AddJT808Client(); | |||||
.AddClient(); | |||||
services.AddHostedService<CleintBenchmarkHostedService>(); | services.AddHostedService<CleintBenchmarkHostedService>(); | ||||
}); | }); | ||||
await serverHostBuilder.RunConsoleAsync(); | await serverHostBuilder.RunConsoleAsync(); | ||||
@@ -25,6 +25,8 @@ namespace JT808.Gateway.CleintBenchmark.Services | |||||
private readonly IJT808TcpClientFactory jT808TcpClientFactory; | private readonly IJT808TcpClientFactory jT808TcpClientFactory; | ||||
private TaskFactory taskFactory; | |||||
public CleintBenchmarkHostedService( | public CleintBenchmarkHostedService( | ||||
ILoggerFactory loggerFactory, | ILoggerFactory loggerFactory, | ||||
IJT808TcpClientFactory jT808TcpClientFactory, | IJT808TcpClientFactory jT808TcpClientFactory, | ||||
@@ -33,6 +35,7 @@ namespace JT808.Gateway.CleintBenchmark.Services | |||||
this.jT808TcpClientFactory = jT808TcpClientFactory; | this.jT808TcpClientFactory = jT808TcpClientFactory; | ||||
clientBenchmarkOptions = clientBenchmarkOptionsAccessor.Value; | clientBenchmarkOptions = clientBenchmarkOptionsAccessor.Value; | ||||
logger = loggerFactory.CreateLogger("CleintBenchmarkHostedService"); | logger = loggerFactory.CreateLogger("CleintBenchmarkHostedService"); | ||||
} | } | ||||
public Task StartAsync(CancellationToken cancellationToken) | public Task StartAsync(CancellationToken cancellationToken) | ||||
{ | { | ||||
@@ -41,24 +44,21 @@ namespace JT808.Gateway.CleintBenchmark.Services | |||||
ThreadPool.GetMaxThreads(out var maxWorkerThreads, out var maxCompletionPortThreads); | ThreadPool.GetMaxThreads(out var maxWorkerThreads, out var maxCompletionPortThreads); | ||||
logger.LogInformation($"GetMinThreads:{minWorkerThreads}-{minCompletionPortThreads}"); | logger.LogInformation($"GetMinThreads:{minWorkerThreads}-{minCompletionPortThreads}"); | ||||
logger.LogInformation($"GetMaxThreads:{maxWorkerThreads}-{maxCompletionPortThreads}"); | logger.LogInformation($"GetMaxThreads:{maxWorkerThreads}-{maxCompletionPortThreads}"); | ||||
taskFactory = new TaskFactory(cancellationToken); | |||||
for (int i=0;i< clientBenchmarkOptions.DeviceCount; i++) | for (int i=0;i< clientBenchmarkOptions.DeviceCount; i++) | ||||
{ | { | ||||
string deviceNo = (i + 1 + clientBenchmarkOptions.DeviceTemplate).ToString(); | |||||
var client = jT808TcpClientFactory.Create(new JT808DeviceConfig(deviceNo, | |||||
clientBenchmarkOptions.IP, | |||||
clientBenchmarkOptions.Port), cancellationToken); | |||||
} | |||||
ThreadPool.QueueUserWorkItem((state) => | |||||
{ | |||||
while (!cancellationToken.IsCancellationRequested) | |||||
{ | |||||
foreach (var item in jT808TcpClientFactory.GetAll()) | |||||
taskFactory.StartNew(async (state) => { | |||||
string deviceNo = ((int)state + 1 + clientBenchmarkOptions.DeviceTemplate).ToString(); | |||||
var client = await jT808TcpClientFactory.Create(new JT808DeviceConfig(deviceNo, | |||||
clientBenchmarkOptions.IP, | |||||
clientBenchmarkOptions.Port), cancellationToken); | |||||
while (!cancellationToken.IsCancellationRequested) | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
int lat = new Random(1000).Next(100000, 180000); | int lat = new Random(1000).Next(100000, 180000); | ||||
int Lng = new Random(1000).Next(100000, 180000); | int Lng = new Random(1000).Next(100000, 180000); | ||||
item.Send(JT808MsgId.位置信息汇报.Create(item.DeviceConfig.TerminalPhoneNo, new JT808_0x0200() | |||||
await client.SendAsync(JT808MsgId.位置信息汇报.Create(client.DeviceConfig.TerminalPhoneNo, new JT808_0x0200() | |||||
{ | { | ||||
Lat = lat, | Lat = lat, | ||||
Lng = Lng, | Lng = Lng, | ||||
@@ -74,10 +74,10 @@ namespace JT808.Gateway.CleintBenchmark.Services | |||||
{ | { | ||||
logger.LogError(ex.Message); | logger.LogError(ex.Message); | ||||
} | } | ||||
await Task.Delay(clientBenchmarkOptions.Interval); | |||||
} | } | ||||
Thread.Sleep(clientBenchmarkOptions.Interval); | |||||
} | |||||
}); | |||||
}, i); | |||||
} | |||||
return Task.CompletedTask; | return Task.CompletedTask; | ||||
} | } | ||||
@@ -30,5 +30,7 @@ | |||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.1" /> | <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.1" /> | ||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.1" /> | <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.1" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | |||||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||||
</ItemGroup> | |||||
</Project> | </Project> |
@@ -10,7 +10,7 @@ namespace JT808.Gateway.Client | |||||
{ | { | ||||
public static class JT808ClientExtensions | public static class JT808ClientExtensions | ||||
{ | { | ||||
public static IJT808Builder AddJT808Client(this IJT808Builder jT808Builder) | |||||
public static IJT808Builder AddClient(this IJT808Builder jT808Builder) | |||||
{ | { | ||||
jT808Builder.Services.AddSingleton<JT808SendAtomicCounterService>(); | jT808Builder.Services.AddSingleton<JT808SendAtomicCounterService>(); | ||||
jT808Builder.Services.AddSingleton<JT808ReceiveAtomicCounterService>(); | jT808Builder.Services.AddSingleton<JT808ReceiveAtomicCounterService>(); | ||||
@@ -19,7 +19,7 @@ namespace JT808.Gateway.Client | |||||
jT808Builder.Services.AddHostedService<JT808ReportHostedService>(); | jT808Builder.Services.AddHostedService<JT808ReportHostedService>(); | ||||
return jT808Builder; | return jT808Builder; | ||||
} | } | ||||
public static IJT808Builder AddJT808Client(this IJT808Builder jT808Builder, IConfiguration Configuration) | |||||
public static IJT808Builder AddClient(this IJT808Builder jT808Builder, IConfiguration Configuration) | |||||
{ | { | ||||
jT808Builder.Services.AddSingleton<JT808SendAtomicCounterService>(); | jT808Builder.Services.AddSingleton<JT808SendAtomicCounterService>(); | ||||
jT808Builder.Services.AddSingleton<JT808ReceiveAtomicCounterService>(); | jT808Builder.Services.AddSingleton<JT808ReceiveAtomicCounterService>(); | ||||
@@ -29,7 +29,7 @@ namespace JT808.Gateway.Client | |||||
return jT808Builder; | return jT808Builder; | ||||
} | } | ||||
public static IJT808Builder AddJT808Client(this IJT808Builder jT808Builder, Action<JT808ReportOptions> reportOptions) | |||||
public static IJT808Builder AddClient(this IJT808Builder jT808Builder, Action<JT808ReportOptions> reportOptions) | |||||
{ | { | ||||
jT808Builder.Services.AddSingleton<JT808SendAtomicCounterService>(); | jT808Builder.Services.AddSingleton<JT808SendAtomicCounterService>(); | ||||
jT808Builder.Services.AddSingleton<JT808ReceiveAtomicCounterService>(); | jT808Builder.Services.AddSingleton<JT808ReceiveAtomicCounterService>(); | ||||
@@ -176,7 +176,7 @@ namespace JT808.Gateway.Client | |||||
consumed = buffer.GetPosition(totalConsumed); | consumed = buffer.GetPosition(totalConsumed); | ||||
} | } | ||||
} | } | ||||
public void Send(JT808ClientRequest message) | |||||
public async ValueTask SendAsync(JT808ClientRequest message) | |||||
{ | { | ||||
if (disposed) return; | if (disposed) return; | ||||
if (IsOpen && socketState) | if (IsOpen && socketState) | ||||
@@ -185,8 +185,9 @@ namespace JT808.Gateway.Client | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
var sendData = JT808Serializer.SerializeReadOnlySpan(message.Package, minBufferSize: message.MinBufferSize); | |||||
clientSocket.Send(sendData); | |||||
var sendData = JT808Serializer.Serialize(message.Package, minBufferSize: message.MinBufferSize); | |||||
//clientSocket.Send(sendData); | |||||
await clientSocket.SendAsync(sendData, SocketFlags.None); | |||||
SendAtomicCounterService.MsgSuccessIncrement(); | SendAtomicCounterService.MsgSuccessIncrement(); | ||||
} | } | ||||
catch (System.Net.Sockets.SocketException ex) | catch (System.Net.Sockets.SocketException ex) | ||||
@@ -6,16 +6,17 @@ using System.Text; | |||||
using JT808.Protocol.Enums; | using JT808.Protocol.Enums; | ||||
using JT808.Protocol.Extensions; | using JT808.Protocol.Extensions; | ||||
using JT808.Gateway.Client.Metadata; | using JT808.Gateway.Client.Metadata; | ||||
using System.Threading.Tasks; | |||||
namespace JT808.Gateway.Client | namespace JT808.Gateway.Client | ||||
{ | { | ||||
public static class JT808TcpClientExtensions | public static class JT808TcpClientExtensions | ||||
{ | { | ||||
public static void Send(this JT808TcpClient client, JT808Package package, int minBufferSize = 4096) | |||||
public static async ValueTask SendAsync(this JT808TcpClient client, JT808Package package, int minBufferSize = 4096) | |||||
{ | { | ||||
package.Header.TerminalPhoneNo = client.DeviceConfig.TerminalPhoneNo; | package.Header.TerminalPhoneNo = client.DeviceConfig.TerminalPhoneNo; | ||||
JT808ClientRequest request = new JT808ClientRequest(package, minBufferSize); | JT808ClientRequest request = new JT808ClientRequest(package, minBufferSize); | ||||
client.Send(request); | |||||
await client.SendAsync(request); | |||||
} | } | ||||
} | } | ||||
@@ -1,7 +1,6 @@ | |||||
using JT808.Gateway.Abstractions; | using JT808.Gateway.Abstractions; | ||||
using JT808.Gateway.InMemoryMQ.Services; | using JT808.Gateway.InMemoryMQ.Services; | ||||
using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||
using Microsoft.Extensions.DependencyInjection.Extensions; | |||||
namespace JT808.Gateway.InMemoryMQ | namespace JT808.Gateway.InMemoryMQ | ||||
{ | { | ||||
@@ -12,14 +11,14 @@ namespace JT808.Gateway.InMemoryMQ | |||||
/// </summary> | /// </summary> | ||||
/// <param name="jT808GatewayBuilder"></param> | /// <param name="jT808GatewayBuilder"></param> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
public static IJT808GatewayBuilder AddJT808ServerInMemoryMQ(this IJT808GatewayBuilder jT808GatewayBuilder) | |||||
public static IJT808GatewayBuilder AddServerInMemoryMQ(this IJT808GatewayBuilder jT808GatewayBuilder) | |||||
{ | { | ||||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<JT808MsgService>(); | jT808GatewayBuilder.JT808Builder.Services.AddSingleton<JT808MsgService>(); | ||||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<JT808ReplyMsgService>(); | jT808GatewayBuilder.JT808Builder.Services.AddSingleton<JT808ReplyMsgService>(); | ||||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgProducer), typeof(JT808MsgProducer), ServiceLifetime.Singleton)); | |||||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgConsumer), typeof(JT808MsgConsumer), ServiceLifetime.Singleton)); | |||||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyProducer), typeof(JT808MsgReplyProducer), ServiceLifetime.Singleton)); | |||||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); | |||||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<IJT808MsgProducer, JT808MsgProducer>(); | |||||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<IJT808MsgConsumer, JT808MsgConsumer>(); | |||||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<IJT808MsgReplyProducer, JT808MsgReplyProducer>(); | |||||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<IJT808MsgReplyConsumer, JT808MsgReplyConsumer>(); | |||||
return jT808GatewayBuilder; | return jT808GatewayBuilder; | ||||
} | } | ||||
} | } |
@@ -21,11 +21,6 @@ namespace JT808.Gateway.InMemoryMQ.Services | |||||
await _channel.Writer.WriteAsync((terminalNo, data)); | await _channel.Writer.WriteAsync((terminalNo, data)); | ||||
} | } | ||||
public bool TryRead(out (string TerminalNo, byte[] Data) item) | |||||
{ | |||||
return _channel.Reader.TryRead(out item); | |||||
} | |||||
public async ValueTask<(string TerminalNo, byte[] Data)> ReadAsync(CancellationToken cancellationToken) | public async ValueTask<(string TerminalNo, byte[] Data)> ReadAsync(CancellationToken cancellationToken) | ||||
{ | { | ||||
return await _channel.Reader.ReadAsync(cancellationToken); | return await _channel.Reader.ReadAsync(cancellationToken); | ||||
@@ -20,12 +20,6 @@ namespace JT808.Gateway.InMemoryMQ.Services | |||||
{ | { | ||||
await _channel.Writer.WriteAsync((terminalNo, data)); | await _channel.Writer.WriteAsync((terminalNo, data)); | ||||
} | } | ||||
public bool TryRead(out (string TerminalNo, byte[] Data) item) | |||||
{ | |||||
return _channel.Reader.TryRead(out item); | |||||
} | |||||
public async ValueTask<(string TerminalNo, byte[] Data)> ReadAsync(CancellationToken cancellationToken) | public async ValueTask<(string TerminalNo, byte[] Data)> ReadAsync(CancellationToken cancellationToken) | ||||
{ | { | ||||
return await _channel.Reader.ReadAsync(cancellationToken); | return await _channel.Reader.ReadAsync(cancellationToken); | ||||
@@ -10,7 +10,7 @@ namespace JT808.Gateway.Kafka | |||||
{ | { | ||||
public static class JT808ClientKafkaExtensions | public static class JT808ClientKafkaExtensions | ||||
{ | { | ||||
public static IJT808ClientBuilder AddJT808ClientKafka(this IJT808Builder builder) | |||||
public static IJT808ClientBuilder AddClientKafka(this IJT808Builder builder) | |||||
{ | { | ||||
return new JT808ClientBuilderDefault(builder); | return new JT808ClientBuilderDefault(builder); | ||||
} | } | ||||
@@ -47,7 +47,7 @@ namespace JT808.Gateway.Kafka | |||||
public static IJT808ClientBuilder AddMsgReplyConsumer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) | public static IJT808ClientBuilder AddMsgReplyConsumer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) | ||||
{ | { | ||||
jT808ClientBuilder.JT808Builder.Services.Configure<JT808MsgReplyConsumerConfig>(configuration.GetSection("JT808MsgReplyConsumerConfig")); | jT808ClientBuilder.JT808Builder.Services.Configure<JT808MsgReplyConsumerConfig>(configuration.GetSection("JT808MsgReplyConsumerConfig")); | ||||
jT808ClientBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); | |||||
jT808ClientBuilder.JT808Builder.Services.TryAddSingleton<IJT808MsgReplyConsumer, JT808MsgReplyConsumer>(); | |||||
return jT808ClientBuilder; | return jT808ClientBuilder; | ||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -14,7 +14,7 @@ namespace JT808.Gateway.Kafka | |||||
/// <param name="jT808GatewayBuilder"></param> | /// <param name="jT808GatewayBuilder"></param> | ||||
/// <param name="configuration">GetSection("JT808MsgProducerConfig")</param> | /// <param name="configuration">GetSection("JT808MsgProducerConfig")</param> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
public static IJT808GatewayBuilder AddJT808ServerKafkaMsgProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||||
public static IJT808GatewayBuilder AddServerKafkaMsgProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||||
{ | { | ||||
jT808GatewayBuilder.JT808Builder.Services.Configure<JT808MsgProducerConfig>(configuration.GetSection("JT808MsgProducerConfig")); | jT808GatewayBuilder.JT808Builder.Services.Configure<JT808MsgProducerConfig>(configuration.GetSection("JT808MsgProducerConfig")); | ||||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgProducer), typeof(JT808MsgProducer), ServiceLifetime.Singleton)); | jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgProducer), typeof(JT808MsgProducer), ServiceLifetime.Singleton)); | ||||
@@ -26,7 +26,7 @@ namespace JT808.Gateway.Kafka | |||||
/// <param name="jT808GatewayBuilder"></param> | /// <param name="jT808GatewayBuilder"></param> | ||||
/// <param name="configuration">GetSection("JT808MsgReplyConsumerConfig")</param> | /// <param name="configuration">GetSection("JT808MsgReplyConsumerConfig")</param> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
public static IJT808GatewayBuilder AddJT808ServerKafkaMsgReplyConsumer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||||
public static IJT808GatewayBuilder AddServerKafkaMsgReplyConsumer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||||
{ | { | ||||
jT808GatewayBuilder.JT808Builder.Services.Configure<JT808MsgReplyConsumerConfig>(configuration.GetSection("JT808MsgReplyConsumerConfig")); | jT808GatewayBuilder.JT808Builder.Services.Configure<JT808MsgReplyConsumerConfig>(configuration.GetSection("JT808MsgReplyConsumerConfig")); | ||||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); | jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); | ||||
@@ -38,7 +38,7 @@ namespace JT808.Gateway.Kafka | |||||
/// <param name="jT808GatewayBuilder"></param> | /// <param name="jT808GatewayBuilder"></param> | ||||
/// <param name="configuration">GetSection("JT808SessionProducerConfig")</param> | /// <param name="configuration">GetSection("JT808SessionProducerConfig")</param> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
public static IJT808GatewayBuilder AddJT808ServerKafkaSessionProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||||
public static IJT808GatewayBuilder AddServerKafkaSessionProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||||
{ | { | ||||
jT808GatewayBuilder.JT808Builder.Services.Configure<JT808SessionProducerConfig>(configuration.GetSection("JT808SessionProducerConfig")); | jT808GatewayBuilder.JT808Builder.Services.Configure<JT808SessionProducerConfig>(configuration.GetSection("JT808SessionProducerConfig")); | ||||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808SessionProducer), typeof(JT808SessionProducer), ServiceLifetime.Singleton)); | jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808SessionProducer), typeof(JT808SessionProducer), ServiceLifetime.Singleton)); | ||||
@@ -51,7 +51,7 @@ namespace JT808.Gateway.ReplyMessage | |||||
/// </summary> | /// </summary> | ||||
/// <param name="jT808GatewayBuilder"></param> | /// <param name="jT808GatewayBuilder"></param> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
public static IJT808GatewayBuilder AddJT808InMemoryReplyMessage(this IJT808GatewayBuilder jT808GatewayBuilder) | |||||
public static IJT808GatewayBuilder AddInMemoryReplyMessage(this IJT808GatewayBuilder jT808GatewayBuilder) | |||||
{ | { | ||||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<JT808ReplyMessageHandler>(); | jT808GatewayBuilder.JT808Builder.Services.AddSingleton<JT808ReplyMessageHandler>(); | ||||
jT808GatewayBuilder.JT808Builder.Services.AddHostedService<JT808ReplyMessageHostedService>(); | jT808GatewayBuilder.JT808Builder.Services.AddHostedService<JT808ReplyMessageHostedService>(); | ||||
@@ -1,8 +0,0 @@ | |||||
{ | |||||
"JT808Configuration": { | |||||
"TcpPort": 808, | |||||
"UdpPort": 808, | |||||
"MiniNumBufferSize": 51200, | |||||
"SoBacklog": 65535 | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | |||||
<TargetFramework>netcoreapp3.1</TargetFramework> | |||||
<IsPackable>false</IsPackable> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> | |||||
<PackageReference Include="xunit" Version="2.4.0" /> | |||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> | |||||
<PackageReference Include="coverlet.collector" Version="1.0.1" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\..\JT808.Gateway.InMemoryMQ\JT808.Gateway.InMemoryMQ.csproj" /> | |||||
</ItemGroup> | |||||
</Project> |
@@ -0,0 +1,22 @@ | |||||
using JT808.Gateway.InMemoryMQ.Services; | |||||
using System; | |||||
using System.Collections.Concurrent; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
using Xunit; | |||||
namespace JT808.Gateway.InMemoryMQ.Test.Services | |||||
{ | |||||
public class JT808MsgServiceTest | |||||
{ | |||||
[Fact] | |||||
public void Test1() | |||||
{ | |||||
JT808MsgService jT808MsgService = new JT808MsgService(); | |||||
jT808MsgService.WriteAsync("132", new byte[] { 1, 2, 3 }).GetAwaiter().GetResult(); | |||||
var result = jT808MsgService.ReadAsync(CancellationToken.None).GetAwaiter().GetResult(); | |||||
Assert.Equal("132", result.TerminalNo); | |||||
Assert.Equal(new byte[] { 1, 2, 3 }, result.Data); | |||||
} | |||||
} | |||||
} |
@@ -22,7 +22,7 @@ | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\JT808.Gateway\JT808.Gateway.csproj" /> | |||||
<ProjectReference Include="..\..\JT808.Gateway\JT808.Gateway.csproj" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
</Project> | </Project> |
@@ -158,7 +158,7 @@ namespace JT808.Gateway.Test.Session | |||||
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); | ||||
jT808SessionManager.TrySendByTerminalPhoneNo(tno, new byte[] { 0x7e, 0, 0, 0x7e }); | |||||
jT808SessionManager.TrySendByTerminalPhoneNoAsync(tno, new byte[] { 0x7e, 0, 0, 0x7e }).GetAwaiter().GetResult(); | |||||
}); | }); | ||||
} | } | ||||
@@ -180,8 +180,8 @@ namespace JT808.Gateway.Test.Session | |||||
Assert.True(jT808SessionManager.TerminalPhoneNoSessions.ContainsKey(tno1)); | Assert.True(jT808SessionManager.TerminalPhoneNoSessions.ContainsKey(tno1)); | ||||
Assert.True(jT808SessionManager.TerminalPhoneNoSessions.ContainsKey(tno2)); | Assert.True(jT808SessionManager.TerminalPhoneNoSessions.ContainsKey(tno2)); | ||||
var sessions = jT808SessionManager.GetTcpAll(); | var sessions = jT808SessionManager.GetTcpAll(); | ||||
Assert.Equal(session1.SessionID, sessions[0].SessionID); | |||||
Assert.Equal(session2.SessionID, sessions[1].SessionID); | |||||
Assert.Contains(sessions, (item) => item.SessionID == session1.SessionID); | |||||
Assert.Contains(sessions, (item) => item.SessionID == session2.SessionID); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -4,6 +4,8 @@ | |||||
<OutputType>Exe</OutputType> | <OutputType>Exe</OutputType> | ||||
<TargetFramework>netcoreapp3.1</TargetFramework> | <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> | <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> | ||||
<!--<ServerGarbageCollection>true</ServerGarbageCollection> | |||||
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>--> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
@@ -14,11 +16,11 @@ | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\JT808.Gateway.Client\JT808.Gateway.Client.csproj" /> | |||||
<ProjectReference Include="..\JT808.Gateway.InMemoryMQ\JT808.Gateway.InMemoryMQ.csproj" /> | |||||
<ProjectReference Include="..\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj" /> | |||||
<ProjectReference Include="..\JT808.Gateway.Services\JT808.Gateway.ReplyMessage\JT808.Gateway.ReplyMessage.csproj" /> | |||||
<ProjectReference Include="..\JT808.Gateway\JT808.Gateway.csproj" /> | |||||
<ProjectReference Include="..\..\JT808.Gateway\JT808.Gateway.csproj" /> | |||||
<ProjectReference Include="..\..\JT808.Gateway.Client\JT808.Gateway.Client.csproj" /> | |||||
<ProjectReference Include="..\..\JT808.Gateway.InMemoryMQ\JT808.Gateway.InMemoryMQ.csproj" /> | |||||
<ProjectReference Include="..\..\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj" /> | |||||
<ProjectReference Include="..\..\JT808.Gateway.Services\JT808.Gateway.ReplyMessage\JT808.Gateway.ReplyMessage.csproj" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> |
@@ -38,7 +38,7 @@ namespace JT808.Gateway.TestHosting.Jobs | |||||
{ | { | ||||
int lat = new Random(1000).Next(100000, 180000); | int lat = new Random(1000).Next(100000, 180000); | ||||
int Lng = new Random(1000).Next(100000, 180000); | int Lng = new Random(1000).Next(100000, 180000); | ||||
client.Send(JT808MsgId.位置信息汇报.Create(client.DeviceConfig.TerminalPhoneNo, new JT808_0x0200() | |||||
client.SendAsync(JT808MsgId.位置信息汇报.Create(client.DeviceConfig.TerminalPhoneNo, new JT808_0x0200() | |||||
{ | { | ||||
Lat = lat, | Lat = lat, | ||||
Lng = Lng, | Lng = Lng, |
@@ -37,23 +37,24 @@ namespace JT808.Gateway.TestHosting | |||||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | services.AddSingleton<ILoggerFactory, LoggerFactory>(); | ||||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | ||||
services.AddJT808Configure() | services.AddJT808Configure() | ||||
//.AddJT808Client() | |||||
//.AddJT808Gateway(options => | |||||
//{ | |||||
// options.TcpPort = 808; | |||||
// options.UdpPort = 808; | |||||
//}) | |||||
.AddJT808Gateway(hostContext.Configuration) | |||||
//添加客户端工具 | |||||
//.AddClient() | |||||
//.AddGateway(options => | |||||
////{ | |||||
//// options.TcpPort = 808; | |||||
//// options.UdpPort = 808; | |||||
////}) | |||||
.AddGateway(hostContext.Configuration) | |||||
.AddTcp() | .AddTcp() | ||||
.AddUdp() | .AddUdp() | ||||
.AddGrpc() | .AddGrpc() | ||||
//InMemoryMQ | //InMemoryMQ | ||||
.AddJT808ServerInMemoryMQ() | |||||
.AddJT808InMemoryReplyMessage() | |||||
.AddServerInMemoryMQ() | |||||
.AddInMemoryReplyMessage() | |||||
//kafka插件 | //kafka插件 | ||||
//.AddJT808ServerKafkaMsgProducer(hostContext.Configuration) | |||||
//.AddJT808ServerKafkaMsgReplyConsumer(hostContext.Configuration) | |||||
//.AddJT808ServerKafkaSessionProducer(hostContext.Configuration) | |||||
//.AddServerKafkaMsgProducer(hostContext.Configuration) | |||||
//.AddServerKafkaMsgReplyConsumer(hostContext.Configuration) | |||||
//.AddServerKafkaSessionProducer(hostContext.Configuration) | |||||
; | ; | ||||
//grpc客户端调用 | //grpc客户端调用 | ||||
//services.AddHostedService<CallGrpcClientJob>(); | //services.AddHostedService<CallGrpcClientJob>(); |
@@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.29409.12 | |||||
MinimumVisualStudioVersion = 10.0.40219.1 | MinimumVisualStudioVersion = 10.0.40219.1 | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway", "JT808.Gateway\JT808.Gateway.csproj", "{4C8A2546-8333-416D-B123-91062B630087}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway", "JT808.Gateway\JT808.Gateway.csproj", "{4C8A2546-8333-416D-B123-91062B630087}" | ||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.TestHosting", "JT808.Gateway.TestHosting\JT808.Gateway.TestHosting.csproj", "{AE40AFE0-0950-442C-A74C-10CDF53E9F36}" | |||||
EndProject | |||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Abstractions", "JT808.Gateway.Abstractions\JT808.Gateway.Abstractions.csproj", "{3AA17DF7-A1B3-449C-93C2-45B051C32933}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Abstractions", "JT808.Gateway.Abstractions\JT808.Gateway.Abstractions.csproj", "{3AA17DF7-A1B3-449C-93C2-45B051C32933}" | ||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Kafka", "JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj", "{274C048E-A8E3-4422-A578-A10A97DF36F2}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Kafka", "JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj", "{274C048E-A8E3-4422-A578-A10A97DF36F2}" | ||||
@@ -31,10 +29,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Client", "JT8 | |||||
EndProject | EndProject | ||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{7CBAACEE-19BF-499A-8C41-36A1324D45E9}" | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{7CBAACEE-19BF-499A-8C41-36A1324D45E9}" | ||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Test", "JT808.Gateway.Test\JT808.Gateway.Test.csproj", "{1E230D1B-BDFC-4D0A-9B34-592280A723BD}" | |||||
EndProject | |||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.CleintBenchmark", "JT808.Gateway.CleintBenchmark\JT808.Gateway.CleintBenchmark.csproj", "{0FBC9E4F-8585-4820-ACF1-145A14B3A727}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.CleintBenchmark", "JT808.Gateway.CleintBenchmark\JT808.Gateway.CleintBenchmark.csproj", "{0FBC9E4F-8585-4820-ACF1-145A14B3A727}" | ||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Test", "JT808.Gateway.Tests\JT808.Gateway.Test\JT808.Gateway.Test.csproj", "{E3DC260E-0B55-4993-B051-402E44D4E883}" | |||||
EndProject | |||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.TestHosting", "JT808.Gateway.Tests\JT808.Gateway.TestHosting\JT808.Gateway.TestHosting.csproj", "{69C815FE-3C32-473E-99C9-F3C4B3BCFF81}" | |||||
EndProject | |||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.InMemoryMQ.Test", "JT808.Gateway.Tests\JT808.Gateway.InMemoryMQ.Test\JT808.Gateway.InMemoryMQ.Test.csproj", "{E103E89D-3069-4AAE-99CE-2AD633AD351E}" | |||||
EndProject | |||||
Global | Global | ||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
Debug|Any CPU = Debug|Any CPU | Debug|Any CPU = Debug|Any CPU | ||||
@@ -45,10 +47,6 @@ Global | |||||
{4C8A2546-8333-416D-B123-91062B630087}.Debug|Any CPU.Build.0 = Debug|Any CPU | {4C8A2546-8333-416D-B123-91062B630087}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
{4C8A2546-8333-416D-B123-91062B630087}.Release|Any CPU.ActiveCfg = Release|Any CPU | {4C8A2546-8333-416D-B123-91062B630087}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
{4C8A2546-8333-416D-B123-91062B630087}.Release|Any CPU.Build.0 = Release|Any CPU | {4C8A2546-8333-416D-B123-91062B630087}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
{AE40AFE0-0950-442C-A74C-10CDF53E9F36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{AE40AFE0-0950-442C-A74C-10CDF53E9F36}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{AE40AFE0-0950-442C-A74C-10CDF53E9F36}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{AE40AFE0-0950-442C-A74C-10CDF53E9F36}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{3AA17DF7-A1B3-449C-93C2-45B051C32933}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {3AA17DF7-A1B3-449C-93C2-45B051C32933}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
{3AA17DF7-A1B3-449C-93C2-45B051C32933}.Debug|Any CPU.Build.0 = Debug|Any CPU | {3AA17DF7-A1B3-449C-93C2-45B051C32933}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
{3AA17DF7-A1B3-449C-93C2-45B051C32933}.Release|Any CPU.ActiveCfg = Release|Any CPU | {3AA17DF7-A1B3-449C-93C2-45B051C32933}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
@@ -89,27 +87,36 @@ Global | |||||
{AC3070AC-A938-4213-A562-C079BB4A3F9E}.Debug|Any CPU.Build.0 = Debug|Any CPU | {AC3070AC-A938-4213-A562-C079BB4A3F9E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
{AC3070AC-A938-4213-A562-C079BB4A3F9E}.Release|Any CPU.ActiveCfg = Release|Any CPU | {AC3070AC-A938-4213-A562-C079BB4A3F9E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
{AC3070AC-A938-4213-A562-C079BB4A3F9E}.Release|Any CPU.Build.0 = Release|Any CPU | {AC3070AC-A938-4213-A562-C079BB4A3F9E}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
{1E230D1B-BDFC-4D0A-9B34-592280A723BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{1E230D1B-BDFC-4D0A-9B34-592280A723BD}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{1E230D1B-BDFC-4D0A-9B34-592280A723BD}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{1E230D1B-BDFC-4D0A-9B34-592280A723BD}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
{0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Debug|Any CPU.Build.0 = Debug|Any CPU | {0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
{0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Release|Any CPU.ActiveCfg = Release|Any CPU | {0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
{0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Release|Any CPU.Build.0 = Release|Any CPU | {0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
{E3DC260E-0B55-4993-B051-402E44D4E883}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{E3DC260E-0B55-4993-B051-402E44D4E883}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{E3DC260E-0B55-4993-B051-402E44D4E883}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{E3DC260E-0B55-4993-B051-402E44D4E883}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{69C815FE-3C32-473E-99C9-F3C4B3BCFF81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{69C815FE-3C32-473E-99C9-F3C4B3BCFF81}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{69C815FE-3C32-473E-99C9-F3C4B3BCFF81}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{69C815FE-3C32-473E-99C9-F3C4B3BCFF81}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{E103E89D-3069-4AAE-99CE-2AD633AD351E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{E103E89D-3069-4AAE-99CE-2AD633AD351E}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{E103E89D-3069-4AAE-99CE-2AD633AD351E}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{E103E89D-3069-4AAE-99CE-2AD633AD351E}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
HideSolutionNode = FALSE | HideSolutionNode = FALSE | ||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(NestedProjects) = preSolution | GlobalSection(NestedProjects) = preSolution | ||||
{AE40AFE0-0950-442C-A74C-10CDF53E9F36} = {7CBAACEE-19BF-499A-8C41-36A1324D45E9} | |||||
{D62E3054-6924-4F1A-9BEF-E52B191F16B6} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | {D62E3054-6924-4F1A-9BEF-E52B191F16B6} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | ||||
{A242A839-4F00-4434-A7E8-7E3BEBA5B75C} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | {A242A839-4F00-4434-A7E8-7E3BEBA5B75C} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | ||||
{1CB84599-5F56-4461-A451-DF16E3854AB9} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | {1CB84599-5F56-4461-A451-DF16E3854AB9} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | ||||
{604BB5CF-9ED1-4D78-9328-59436E2B4EB4} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | {604BB5CF-9ED1-4D78-9328-59436E2B4EB4} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | ||||
{598E445A-AF2E-42F0-98F4-18EC22E473FC} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | {598E445A-AF2E-42F0-98F4-18EC22E473FC} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | ||||
{8FCC6D65-8A49-4AE7-8B19-F255100849D6} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | {8FCC6D65-8A49-4AE7-8B19-F255100849D6} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | ||||
{1E230D1B-BDFC-4D0A-9B34-592280A723BD} = {7CBAACEE-19BF-499A-8C41-36A1324D45E9} | |||||
{E3DC260E-0B55-4993-B051-402E44D4E883} = {7CBAACEE-19BF-499A-8C41-36A1324D45E9} | |||||
{69C815FE-3C32-473E-99C9-F3C4B3BCFF81} = {7CBAACEE-19BF-499A-8C41-36A1324D45E9} | |||||
{E103E89D-3069-4AAE-99CE-2AD633AD351E} = {7CBAACEE-19BF-499A-8C41-36A1324D45E9} | |||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(ExtensibilityGlobals) = postSolution | GlobalSection(ExtensibilityGlobals) = postSolution | ||||
SolutionGuid = {AA9303A7-6FB3-4572-88AA-3302E85330D1} | SolutionGuid = {AA9303A7-6FB3-4572-88AA-3302E85330D1} | ||||
@@ -16,7 +16,7 @@ namespace JT808.Gateway | |||||
{ | { | ||||
public static partial class JT808GatewayExtensions | public static partial class JT808GatewayExtensions | ||||
{ | { | ||||
public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder,Action<JT808Configuration> config) | |||||
public static IJT808GatewayBuilder AddGateway(this IJT808Builder jt808Builder,Action<JT808Configuration> config) | |||||
{ | { | ||||
IJT808GatewayBuilder server = new JT808GatewayBuilderDefault(jt808Builder); | IJT808GatewayBuilder server = new JT808GatewayBuilderDefault(jt808Builder); | ||||
server.JT808Builder.Services.Configure(config); | server.JT808Builder.Services.Configure(config); | ||||
@@ -24,7 +24,7 @@ namespace JT808.Gateway | |||||
return server; | return server; | ||||
} | } | ||||
public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder, IConfiguration configuration) | |||||
public static IJT808GatewayBuilder AddGateway(this IJT808Builder jt808Builder, IConfiguration configuration) | |||||
{ | { | ||||
IJT808GatewayBuilder server = new JT808GatewayBuilderDefault(jt808Builder); | IJT808GatewayBuilder server = new JT808GatewayBuilderDefault(jt808Builder); | ||||
server.JT808Builder.Services.Configure<JT808Configuration>(configuration.GetSection("JT808Configuration")); | server.JT808Builder.Services.Configure<JT808Configuration>(configuration.GetSection("JT808Configuration")); | ||||
@@ -21,7 +21,7 @@ using Microsoft.Extensions.Options; | |||||
namespace JT808.Gateway | namespace JT808.Gateway | ||||
{ | { | ||||
public class JT808TcpServer:IHostedService | |||||
public class JT808TcpServer : IHostedService | |||||
{ | { | ||||
private readonly Socket server; | private readonly Socket server; | ||||
@@ -44,34 +44,38 @@ namespace JT808.Gateway | |||||
JT808SessionManager jT808SessionManager, | JT808SessionManager jT808SessionManager, | ||||
IJT808MsgProducer jT808MsgProducer, | IJT808MsgProducer jT808MsgProducer, | ||||
JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory) | JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory) | ||||
{ | |||||
SessionManager = jT808SessionManager; | |||||
Logger = loggerFactory.CreateLogger("JT808TcpServer"); | |||||
Serializer = jT808Config.GetSerializer(); | |||||
MsgProducer = jT808MsgProducer; | |||||
AtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808TransportProtocolType.tcp); | |||||
Configuration = jT808ConfigurationAccessor.Value; | |||||
var IPEndPoint = new System.Net.IPEndPoint(IPAddress.Any, Configuration.TcpPort); | |||||
server = new Socket(IPEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | |||||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true); | |||||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); | |||||
server.LingerState = new LingerOption(false, 0); | |||||
server.Bind(IPEndPoint); | |||||
server.Listen(Configuration.SoBacklog); | |||||
} | |||||
{ | |||||
SessionManager = jT808SessionManager; | |||||
Logger = loggerFactory.CreateLogger("JT808TcpServer"); | |||||
Serializer = jT808Config.GetSerializer(); | |||||
MsgProducer = jT808MsgProducer; | |||||
AtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808TransportProtocolType.tcp); | |||||
Configuration = jT808ConfigurationAccessor.Value; | |||||
var IPEndPoint = new System.Net.IPEndPoint(IPAddress.Any, Configuration.TcpPort); | |||||
server = new Socket(IPEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | |||||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true); | |||||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); | |||||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, Configuration.MiniNumBufferSize); | |||||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, Configuration.MiniNumBufferSize); | |||||
server.LingerState = new LingerOption(false, 0); | |||||
server.Bind(IPEndPoint); | |||||
server.Listen(Configuration.SoBacklog); | |||||
} | |||||
public Task StartAsync(CancellationToken cancellationToken) | public Task StartAsync(CancellationToken cancellationToken) | ||||
{ | { | ||||
Logger.LogInformation($"JT808 TCP Server start at {IPAddress.Any}:{Configuration.TcpPort}."); | Logger.LogInformation($"JT808 TCP Server start at {IPAddress.Any}:{Configuration.TcpPort}."); | ||||
Task.Run(async() => { | |||||
Task.Factory.StartNew(async () => | |||||
{ | |||||
while (!cancellationToken.IsCancellationRequested) | while (!cancellationToken.IsCancellationRequested) | ||||
{ | { | ||||
var socket = await server.AcceptAsync(); | var socket = await server.AcceptAsync(); | ||||
JT808TcpSession jT808TcpSession = new JT808TcpSession(socket); | JT808TcpSession jT808TcpSession = new JT808TcpSession(socket); | ||||
SessionManager.TryAdd(jT808TcpSession); | |||||
await Task.Factory.StartNew(async (state) => | await Task.Factory.StartNew(async (state) => | ||||
{ | { | ||||
var session = (JT808TcpSession)state; | var session = (JT808TcpSession)state; | ||||
SessionManager.TryAdd(session); | |||||
if (Logger.IsEnabled(LogLevel.Information)) | if (Logger.IsEnabled(LogLevel.Information)) | ||||
{ | { | ||||
Logger.LogInformation($"[Connected]:{session.Client.RemoteEndPoint}"); | Logger.LogInformation($"[Connected]:{session.Client.RemoteEndPoint}"); | ||||
@@ -86,7 +90,7 @@ namespace JT808.Gateway | |||||
}, cancellationToken); | }, cancellationToken); | ||||
return Task.CompletedTask; | return Task.CompletedTask; | ||||
} | } | ||||
private async Task FillPipeAsync(JT808TcpSession session, PipeWriter writer) | |||||
private async Task FillPipeAsync(JT808TcpSession session, PipeWriter writer) | |||||
{ | { | ||||
while (true) | while (true) | ||||
{ | { | ||||
@@ -101,7 +105,7 @@ namespace JT808.Gateway | |||||
} | } | ||||
writer.Advance(bytesRead); | writer.Advance(bytesRead); | ||||
} | } | ||||
catch(OperationCanceledException ex) | |||||
catch (OperationCanceledException ex) | |||||
{ | { | ||||
Logger.LogError($"[Receive Timeout]:{session.Client.RemoteEndPoint}"); | Logger.LogError($"[Receive Timeout]:{session.Client.RemoteEndPoint}"); | ||||
break; | break; | ||||
@@ -126,7 +130,7 @@ namespace JT808.Gateway | |||||
} | } | ||||
writer.Complete(); | writer.Complete(); | ||||
} | } | ||||
private async Task ReadPipeAsync(JT808TcpSession session, PipeReader reader) | |||||
private async Task ReadPipeAsync(JT808TcpSession session, PipeReader reader) | |||||
{ | { | ||||
while (true) | while (true) | ||||
{ | { | ||||
@@ -143,13 +147,13 @@ namespace JT808.Gateway | |||||
if (result.IsCanceled) break; | if (result.IsCanceled) break; | ||||
if (buffer.Length > 0) | if (buffer.Length > 0) | ||||
{ | { | ||||
ReaderBuffer(ref buffer, session,out consumed, out examined); | |||||
ReaderBuffer(ref buffer, session, out consumed, out examined); | |||||
} | } | ||||
} | } | ||||
#pragma warning disable CA1031 // Do not catch general exception types | #pragma warning disable CA1031 // Do not catch general exception types | ||||
catch (Exception ex) | catch (Exception ex) | ||||
{ | { | ||||
SessionManager.RemoveBySessionId(session.SessionID); | |||||
Logger.LogError(ex, $"[ReadPipe Error]:{session.Client.RemoteEndPoint}"); | |||||
break; | break; | ||||
} | } | ||||
#pragma warning restore CA1031 // Do not catch general exception types | #pragma warning restore CA1031 // Do not catch general exception types | ||||
@@ -160,7 +164,7 @@ namespace JT808.Gateway | |||||
} | } | ||||
reader.Complete(); | reader.Complete(); | ||||
} | } | ||||
private void ReaderBuffer(ref ReadOnlySequence<byte> buffer, JT808TcpSession session, out SequencePosition consumed, out SequencePosition examined) | |||||
private void ReaderBuffer(ref ReadOnlySequence<byte> buffer, JT808TcpSession session, out SequencePosition consumed, out SequencePosition examined) | |||||
{ | { | ||||
consumed = buffer.Start; | consumed = buffer.Start; | ||||
examined = buffer.End; | examined = buffer.End; | ||||
@@ -177,22 +181,22 @@ namespace JT808.Gateway | |||||
{ | { | ||||
if (mark == 1) | if (mark == 1) | ||||
{ | { | ||||
ReadOnlySpan<byte> contentSpan=ReadOnlySpan<byte>.Empty; | |||||
ReadOnlySpan<byte> contentSpan = ReadOnlySpan<byte>.Empty; | |||||
try | try | ||||
{ | { | ||||
contentSpan = seqReader.Sequence.Slice(totalConsumed, seqReader.Consumed - totalConsumed).FirstSpan; | contentSpan = seqReader.Sequence.Slice(totalConsumed, seqReader.Consumed - totalConsumed).FirstSpan; | ||||
var package = Serializer.HeaderDeserialize(contentSpan,minBufferSize:10240); | |||||
var package = Serializer.HeaderDeserialize(contentSpan, minBufferSize: 10240); | |||||
AtomicCounterService.MsgSuccessIncrement(); | AtomicCounterService.MsgSuccessIncrement(); | ||||
if (Logger.IsEnabled(LogLevel.Debug)) Logger.LogDebug($"[Atomic Success Counter]:{AtomicCounterService.MsgSuccessCount}"); | if (Logger.IsEnabled(LogLevel.Debug)) Logger.LogDebug($"[Atomic Success Counter]:{AtomicCounterService.MsgSuccessCount}"); | ||||
if (Logger.IsEnabled(LogLevel.Trace)) Logger.LogTrace($"[Accept Hex {session.Client.RemoteEndPoint}]:{package.OriginalData.ToArray().ToHexString()}"); | if (Logger.IsEnabled(LogLevel.Trace)) Logger.LogTrace($"[Accept Hex {session.Client.RemoteEndPoint}]:{package.OriginalData.ToArray().ToHexString()}"); | ||||
SessionManager.TryLink(package.Header.TerminalPhoneNo, session); | SessionManager.TryLink(package.Header.TerminalPhoneNo, session); | ||||
MsgProducer.ProduceAsync(package.Header.TerminalPhoneNo, package.OriginalData.ToArray()); | |||||
MsgProducer.ProduceAsync(package.Header.TerminalPhoneNo, package.OriginalData.ToArray()); | |||||
} | } | ||||
catch (JT808Exception ex) | catch (JT808Exception ex) | ||||
{ | { | ||||
AtomicCounterService.MsgFailIncrement(); | AtomicCounterService.MsgFailIncrement(); | ||||
if (Logger.IsEnabled(LogLevel.Information)) Logger.LogInformation($"[Atomic Fail Counter]:{AtomicCounterService.MsgFailCount}"); | if (Logger.IsEnabled(LogLevel.Information)) Logger.LogInformation($"[Atomic Fail Counter]:{AtomicCounterService.MsgFailCount}"); | ||||
Logger.LogError($"[HeaderDeserialize ErrorCode]:{ ex.ErrorCode},[ReaderBuffer]:{contentSpan.ToArray().ToHexString()}"); | |||||
Logger.LogError($"[HeaderDeserialize ErrorCode]:{ ex.ErrorCode},[ReaderBuffer]:{contentSpan.ToArray().ToHexString()}"); | |||||
} | } | ||||
totalConsumed += (seqReader.Consumed - totalConsumed); | totalConsumed += (seqReader.Consumed - totalConsumed); | ||||
if (seqReader.End) break; | if (seqReader.End) break; | ||||
@@ -206,7 +210,7 @@ namespace JT808.Gateway | |||||
seqReader.Advance(1); | seqReader.Advance(1); | ||||
} | } | ||||
} | } | ||||
if (seqReader.Length== totalConsumed) | |||||
if (seqReader.Length == totalConsumed) | |||||
{ | { | ||||
examined = consumed = buffer.End; | examined = consumed = buffer.End; | ||||
} | } | ||||
@@ -93,17 +93,17 @@ namespace JT808.Gateway.Services | |||||
return Task.FromResult(reply); | return Task.FromResult(reply); | ||||
} | } | ||||
public override Task<UnificationSendReply> UnificationSend(UnificationSendRequest request, ServerCallContext context) | |||||
public override async Task<UnificationSendReply> UnificationSend(UnificationSendRequest request, ServerCallContext context) | |||||
{ | { | ||||
Auth(context); | Auth(context); | ||||
try | try | ||||
{ | { | ||||
var flag = jT808SessionManager.TrySendByTerminalPhoneNo(request.TerminalPhoneNo, request.Data.ToByteArray()); | |||||
return Task.FromResult(new UnificationSendReply { Success = flag }); | |||||
var flag = await jT808SessionManager.TrySendByTerminalPhoneNoAsync(request.TerminalPhoneNo, request.Data.ToByteArray()); | |||||
return new UnificationSendReply { Success = flag }; | |||||
} | } | ||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
return Task.FromResult(new UnificationSendReply { Success = false }); | |||||
return new UnificationSendReply { Success = false }; | |||||
} | } | ||||
} | } | ||||
@@ -2,6 +2,9 @@ | |||||
using JT808.Gateway.Configurations; | using JT808.Gateway.Configurations; | ||||
using JT808.Gateway.Session; | using JT808.Gateway.Session; | ||||
using Microsoft.Extensions.Hosting; | using Microsoft.Extensions.Hosting; | ||||
using Microsoft.Extensions.Logging; | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
@@ -12,6 +15,7 @@ namespace JT808.Gateway.Services | |||||
private readonly JT808SessionManager JT808SessionManager; | private readonly JT808SessionManager JT808SessionManager; | ||||
private readonly IJT808MsgReplyConsumer JT808MsgReplyConsumer; | private readonly IJT808MsgReplyConsumer JT808MsgReplyConsumer; | ||||
public JT808MsgReplyHostedService( | public JT808MsgReplyHostedService( | ||||
IJT808MsgReplyConsumer jT808MsgReplyConsumer, | IJT808MsgReplyConsumer jT808MsgReplyConsumer, | ||||
JT808SessionManager jT808SessionManager) | JT808SessionManager jT808SessionManager) | ||||
@@ -22,9 +26,9 @@ namespace JT808.Gateway.Services | |||||
public Task StartAsync(CancellationToken cancellationToken) | public Task StartAsync(CancellationToken cancellationToken) | ||||
{ | { | ||||
JT808MsgReplyConsumer.OnMessage(item => | |||||
JT808MsgReplyConsumer.OnMessage(async(item) => | |||||
{ | { | ||||
JT808SessionManager.TrySendByTerminalPhoneNo(item.TerminalNo, item.Data); | |||||
await JT808SessionManager.TrySendByTerminalPhoneNoAsync(item.TerminalNo, item.Data); | |||||
}); | }); | ||||
JT808MsgReplyConsumer.Subscribe(); | JT808MsgReplyConsumer.Subscribe(); | ||||
return Task.CompletedTask; | return Task.CompletedTask; | ||||
@@ -8,6 +8,7 @@ using System.Collections.Generic; | |||||
using System.Linq; | using System.Linq; | ||||
using System.Net; | using System.Net; | ||||
using System.Net.Sockets; | using System.Net.Sockets; | ||||
using System.Threading.Tasks; | |||||
namespace JT808.Gateway.Session | namespace JT808.Gateway.Session | ||||
{ | { | ||||
@@ -66,36 +67,40 @@ namespace JT808.Gateway.Session | |||||
internal void TryLink(string terminalPhoneNo, IJT808Session session) | internal void TryLink(string terminalPhoneNo, IJT808Session session) | ||||
{ | { | ||||
DateTime curretDatetime= DateTime.Now; | DateTime curretDatetime= DateTime.Now; | ||||
session.ActiveTime = curretDatetime; | |||||
session.TerminalPhoneNo = terminalPhoneNo; | |||||
Sessions.TryUpdate(session.SessionID, session, session); | |||||
TerminalPhoneNoSessions.AddOrUpdate(terminalPhoneNo, session, (key, oldValue)=> | |||||
if (TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo,out IJT808Session cacheSession)) | |||||
{ | { | ||||
if(session.SessionID!= oldValue.SessionID) | |||||
if (session.SessionID != cacheSession.SessionID) | |||||
{ | { | ||||
//从转发到直连的数据需要更新缓存 | |||||
session.ActiveTime = curretDatetime; | |||||
TerminalPhoneNoSessions.TryUpdate(terminalPhoneNo, session, cacheSession); | |||||
//会话通知 | //会话通知 | ||||
JT808SessionProducer?.ProduceAsync(JT808GatewayConstants.SessionOnline, key); | |||||
return session; | |||||
JT808SessionProducer?.ProduceAsync(JT808GatewayConstants.SessionOnline, terminalPhoneNo); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
oldValue.StartTime = curretDatetime; | |||||
cacheSession.ActiveTime = curretDatetime; | |||||
TerminalPhoneNoSessions.TryUpdate(terminalPhoneNo, cacheSession, cacheSession); | |||||
} | } | ||||
return oldValue; | |||||
}); | |||||
} | |||||
else | |||||
{ | |||||
if(TerminalPhoneNoSessions.TryAdd(terminalPhoneNo, session)) | |||||
{ | |||||
//会话通知 | |||||
JT808SessionProducer?.ProduceAsync(JT808GatewayConstants.SessionOnline, terminalPhoneNo); | |||||
} | |||||
} | |||||
} | } | ||||
public IJT808Session TryLink(string terminalPhoneNo, Socket socket, EndPoint remoteEndPoint) | public IJT808Session TryLink(string terminalPhoneNo, Socket socket, EndPoint remoteEndPoint) | ||||
{ | { | ||||
if (TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo, out IJT808Session currentSession)) | if (TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo, out IJT808Session currentSession)) | ||||
{ | { | ||||
if (Sessions.TryGetValue(currentSession.SessionID, out IJT808Session sessionInfo)) | |||||
{ | |||||
sessionInfo.ActiveTime = DateTime.Now; | |||||
sessionInfo.TerminalPhoneNo = terminalPhoneNo; | |||||
sessionInfo.RemoteEndPoint = remoteEndPoint; | |||||
Sessions.TryUpdate(currentSession.SessionID, sessionInfo, sessionInfo); | |||||
} | |||||
currentSession.ActiveTime = DateTime.Now; | |||||
currentSession.TerminalPhoneNo = terminalPhoneNo; | |||||
currentSession.RemoteEndPoint = remoteEndPoint; | |||||
TerminalPhoneNoSessions.TryUpdate(terminalPhoneNo, currentSession, currentSession); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -118,17 +123,17 @@ namespace JT808.Gateway.Session | |||||
return Sessions.TryAdd(session.SessionID, session); | return Sessions.TryAdd(session.SessionID, session); | ||||
} | } | ||||
public bool TrySendByTerminalPhoneNo(string terminalPhoneNo, byte[] data) | |||||
public async ValueTask<bool> TrySendByTerminalPhoneNoAsync(string terminalPhoneNo, byte[] data) | |||||
{ | { | ||||
if(TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo,out var session)) | if(TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo,out var session)) | ||||
{ | { | ||||
if (session.TransportProtocolType == JT808TransportProtocolType.tcp) | if (session.TransportProtocolType == JT808TransportProtocolType.tcp) | ||||
{ | { | ||||
session.Client.Send(data, SocketFlags.None); | |||||
await session.Client.SendAsync(data, SocketFlags.None); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
session.Client.SendTo(data, SocketFlags.None, session.RemoteEndPoint); | |||||
await session.Client.SendToAsync(data, SocketFlags.None, session.RemoteEndPoint); | |||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
@@ -138,17 +143,17 @@ namespace JT808.Gateway.Session | |||||
} | } | ||||
} | } | ||||
public bool TrySendBySessionId(string sessionId, byte[] data) | |||||
public async ValueTask<bool> TrySendBySessionIdAsync(string sessionId, byte[] data) | |||||
{ | { | ||||
if (Sessions.TryGetValue(sessionId, out var session)) | if (Sessions.TryGetValue(sessionId, out var session)) | ||||
{ | { | ||||
if(session.TransportProtocolType== JT808TransportProtocolType.tcp) | if(session.TransportProtocolType== JT808TransportProtocolType.tcp) | ||||
{ | { | ||||
session.Client.Send(data, SocketFlags.None); | |||||
await session.Client.SendAsync(data, SocketFlags.None); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
session.Client.SendTo(data, SocketFlags.None, session.RemoteEndPoint); | |||||
await session.Client.SendToAsync(data, SocketFlags.None, session.RemoteEndPoint); | |||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
@@ -208,12 +213,12 @@ namespace JT808.Gateway.Session | |||||
public List<JT808TcpSession> GetTcpAll() | public List<JT808TcpSession> GetTcpAll() | ||||
{ | { | ||||
return Sessions.Where(w => w.Value.TransportProtocolType == JT808TransportProtocolType.tcp).Select(s => (JT808TcpSession)s.Value).ToList(); | |||||
return TerminalPhoneNoSessions.Where(w => w.Value.TransportProtocolType == JT808TransportProtocolType.tcp).Select(s => (JT808TcpSession)s.Value).ToList(); | |||||
} | } | ||||
public List<JT808UdpSession> GetUdpAll() | public List<JT808UdpSession> GetUdpAll() | ||||
{ | { | ||||
return Sessions.Where(w => w.Value.TransportProtocolType == JT808TransportProtocolType.udp).Select(s => (JT808UdpSession)s.Value).ToList(); | |||||
return TerminalPhoneNoSessions.Where(w => w.Value.TransportProtocolType == JT808TransportProtocolType.udp).Select(s => (JT808UdpSession)s.Value).ToList(); | |||||
} | } | ||||
} | } | ||||
} | } |