-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
364 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using NewLife.Log; | ||
using NewLife.Remoting; | ||
using XCode.Membership; | ||
|
||
namespace Zero.RpcServer; | ||
|
||
/// <summary>地区控制器。会话获取,请求过滤</summary> | ||
[Api("Area")] | ||
internal class AreaController : IApi, IActionFilter | ||
{ | ||
/// <summary>会话。同一Tcp/Udp会话多次请求共用,执行服务方法前赋值</summary> | ||
public IApiSession Session { get; set; } | ||
|
||
[Api(nameof(FindByID))] | ||
public Area FindByID(Int32 id) | ||
{ | ||
// Session 用法同Web | ||
var times = Session["Times"].ToInt(); | ||
times++; | ||
Session["Times"] = times; | ||
|
||
// 故意制造异常 | ||
if (times >= 2) | ||
{ | ||
// 取得当前上下文 | ||
var ctx = ControllerContext.Current; | ||
|
||
throw new ApiException(507, $"[{ctx.ActionName}]调用次数过多!Times={times}"); | ||
} | ||
|
||
return Area.FindByID(id); | ||
} | ||
|
||
/// <summary>本控制器执行前</summary> | ||
/// <param name="filterContext"></param> | ||
public void OnActionExecuting(ControllerContext filterContext) | ||
{ | ||
// 请求参数 | ||
var ps = filterContext.Parameters; | ||
|
||
// 服务参数 | ||
var cs = filterContext.ActionParameters; | ||
|
||
foreach (var item in ps) | ||
{ | ||
if (cs != null && !cs.ContainsKey(item.Key)) | ||
XTrace.WriteLine("服务[{0}]未能找到匹配参数 {1}={2}", filterContext.ActionName, item.Key, item.Value); | ||
} | ||
} | ||
|
||
/// <summary>本控制器执行后,包括异常发生</summary> | ||
/// <param name="filterContext"></param> | ||
public void OnActionExecuted(ControllerContext filterContext) | ||
{ | ||
var ex = filterContext.Exception; | ||
if (ex != null && !filterContext.ExceptionHandled) | ||
{ | ||
XTrace.WriteLine("控制器拦截到异常:{0}", ex.Message); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
using System.Net.Sockets; | ||
using System.Text; | ||
using NewLife; | ||
using NewLife.Log; | ||
using NewLife.Remoting; | ||
using NewLife.Security; | ||
using NewLife.Serialization; | ||
|
||
namespace Zero.RpcServer; | ||
|
||
static class ClientTest | ||
{ | ||
/// <summary>Tcp连接ApiServer</summary> | ||
public static async void TcpTest(Int32 port) | ||
{ | ||
await Task.Delay(1_000); | ||
XTrace.WriteLine(""); | ||
XTrace.WriteLine("Tcp开始连接!"); | ||
|
||
// 连接服务端 | ||
var client = new ApiClient("tcp://127.0.0.2:12346"); | ||
client.Open(); | ||
|
||
await Process(client); | ||
|
||
// 关闭连接 | ||
client.Close("测试完成"); | ||
} | ||
|
||
/// <summary>Udp连接ApiServer</summary> | ||
public static async void UdpTest(Int32 port) | ||
{ | ||
await Task.Delay(2_000); | ||
XTrace.WriteLine(""); | ||
XTrace.WriteLine("Udp开始连接!"); | ||
|
||
// 连接服务端 | ||
var client = new ApiClient("udp://127.0.0.2:12346"); | ||
client.Open(); | ||
|
||
await Process(client); | ||
|
||
// 关闭连接 | ||
client.Close("测试完成"); | ||
} | ||
|
||
/// <summary>Tcp连接ApiServer</summary> | ||
public static async void WebSocketTest(Int32 port) | ||
{ | ||
await Task.Delay(3_000); | ||
XTrace.WriteLine(""); | ||
XTrace.WriteLine("WebSocket开始连接!"); | ||
|
||
// 连接服务端 | ||
var client = new ApiClient("ws://127.0.0.2:12346"); | ||
client.Open(); | ||
|
||
await Process(client); | ||
|
||
// 关闭连接 | ||
client.Close("测试完成"); | ||
} | ||
|
||
static async Task Process(ApiClient client) | ||
{ | ||
// 获取所有接口 | ||
var apis = await client.InvokeAsync<String[]>("api/all"); | ||
client.WriteLog("共有接口数:{0}", apis.Length); | ||
|
||
// 获取服务端信息 | ||
var state = Rand.NextString(8); | ||
var state2 = Rand.NextString(8); | ||
var infs = await client.InvokeAsync<IDictionary<String, Object>>("api/info", new { state, state2 }); | ||
client.WriteLog("服务端信息:{0}", infs.ToJson(true)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using NewLife; | ||
using NewLife.Data; | ||
|
||
namespace Zero.RpcServer; | ||
|
||
/// <summary>自定义控制器。包含多个服务</summary> | ||
/// <remarks> | ||
/// 控制器规范: | ||
/// 1,控制器类不要求公开可见,也无需继承任何基类,需要明码注册到服务端 | ||
/// 2,控制器类中的方法不要求公开可见,但方法名和参数名必须固定,跟客户端一致 | ||
/// 3,第一段路径名为控制器名(去掉Controller),第二段路径名为方法名,如/Area/FindByID | ||
/// 4,通过[Api]特性指定控制器名和方法名 | ||
/// </remarks> | ||
internal class MyController | ||
{ | ||
/// <summary>添加,标准业务服务,走Json序列化</summary> | ||
/// <param name="x"></param> | ||
/// <param name="y"></param> | ||
/// <returns></returns> | ||
public Int32 Add(Int32 x, Int32 y) => x + y; | ||
|
||
/// <summary>RC4加解密,高速业务服务,二进制收发不经序列化</summary> | ||
/// <param name="pk"></param> | ||
/// <returns></returns> | ||
public Packet RC4(Packet pk) | ||
{ | ||
var data = pk.ToArray(); | ||
var pass = "NewLife".GetBytes(); | ||
|
||
return data.RC4(pass); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using NewLife.Caching; | ||
using NewLife.Caching.Services; | ||
using NewLife.Log; | ||
using NewLife.Model; | ||
using NewLife.Remoting; | ||
using Stardust; | ||
using Zero.RpcServer; | ||
|
||
// 启用控制台日志,拦截所有异常 | ||
XTrace.UseConsole(); | ||
|
||
var services = ObjectContainer.Current; | ||
|
||
// 配置星尘。自动读取配置文件 config/star.config 中的服务器地址、应用标识、密钥 | ||
var star = services.AddStardust(); | ||
|
||
// 默认内存缓存,如有配置RedisCache可使用Redis缓存 | ||
services.AddSingleton<ICacheProvider, RedisCacheProvider>(); | ||
|
||
// 引入Redis,用于消息队列和缓存,单例,带性能跟踪。一般使用上面的ICacheProvider替代 | ||
//services.AddRedis("127.0.0.1:6379", "123456", 3, 5000); | ||
|
||
// 实例化RPC服务端,指定端口,同时在Tcp/Udp/IPv4/IPv6上监听 | ||
var server = new ApiServer(12346) | ||
{ | ||
Name = "银河服务端", | ||
|
||
// 指定编码器 | ||
Encoder = new JsonEncoder(), | ||
|
||
//EncoderLog = XTrace.Log, | ||
Log = XTrace.Log, | ||
Tracer = star.Tracer, | ||
}; | ||
|
||
// 注册服务控制器 | ||
server.Register<MyController>(); | ||
server.Register<UserController>(); | ||
server.Register<AreaController>(); | ||
|
||
#if DEBUG | ||
// 打开编码日志 | ||
server.EncoderLog = XTrace.Log; | ||
#endif | ||
|
||
// 启动网络服务,监听端口,所有逻辑将在 xxxController 中处理 | ||
server.Start(); | ||
XTrace.WriteLine("服务端启动完成!"); | ||
|
||
// 注册到星尘,非必须 | ||
star?.Service?.Register("MyRpcServer", () => $"tcp://*:{server.Port},udp://*:{server.Port}"); | ||
|
||
// 客户端测试,非服务端代码,正式使用时请注释掉 | ||
_ = Task.Run(() => ClientTest.TcpTest(server.Port)); | ||
_ = Task.Run(() => ClientTest.UdpTest(server.Port)); | ||
_ = Task.Run(() => ClientTest.WebSocketTest(server.Port)); | ||
|
||
// 阻塞,等待友好退出 | ||
var host = services.BuildHost(); | ||
await host.RunAsync(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using NewLife.Log; | ||
using NewLife.Remoting; | ||
using XCode.Membership; | ||
|
||
namespace Zero.RpcServer; | ||
|
||
/// <summary>产品控制器。会话获取,请求过滤</summary> | ||
[Api("User")] | ||
internal class UserController : IApi, IActionFilter | ||
{ | ||
/// <summary>会话。同一Tcp/Udp会话多次请求共用,执行服务方法前赋值</summary> | ||
public IApiSession Session { get; set; } | ||
|
||
[Api(nameof(FindByID))] | ||
public User FindByID(Int32 id) | ||
{ | ||
// Session 用法同Web | ||
var times = Session["Times"].ToInt(); | ||
times++; | ||
Session["Times"] = times; | ||
|
||
// 故意制造异常 | ||
if (times >= 2) | ||
{ | ||
// 取得当前上下文 | ||
var ctx = ControllerContext.Current; | ||
|
||
throw new ApiException(507, $"[{ctx.ActionName}]调用次数过多!Times={times}"); | ||
} | ||
|
||
return User.FindByID(id); | ||
} | ||
|
||
/// <summary>本控制器执行前</summary> | ||
/// <param name="filterContext"></param> | ||
public void OnActionExecuting(ControllerContext filterContext) | ||
{ | ||
// 请求参数 | ||
var ps = filterContext.Parameters; | ||
|
||
// 服务参数 | ||
var cs = filterContext.ActionParameters; | ||
|
||
foreach (var item in ps) | ||
{ | ||
if (cs != null && !cs.ContainsKey(item.Key)) | ||
XTrace.WriteLine("服务[{0}]未能找到匹配参数 {1}={2}", filterContext.ActionName, item.Key, item.Value); | ||
} | ||
} | ||
|
||
/// <summary>本控制器执行后,包括异常发生</summary> | ||
/// <param name="filterContext"></param> | ||
public void OnActionExecuted(ControllerContext filterContext) | ||
{ | ||
var ex = filterContext.Exception; | ||
if (ex != null && !filterContext.ExceptionHandled) | ||
{ | ||
XTrace.WriteLine("控制器拦截到异常:{0}", ex.Message); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<AssemblyTitle>RPC服务端</AssemblyTitle> | ||
<Description>高性能,长连接,数据接口</Description> | ||
<Company>新生命开发团队</Company> | ||
<Copyright>©2002-2024 NewLife</Copyright> | ||
<VersionPrefix>1.0</VersionPrefix> | ||
<VersionSuffix>$([System.DateTime]::Now.ToString(`yyyy.MMdd`))</VersionSuffix> | ||
<Version>$(VersionPrefix).$(VersionSuffix)</Version> | ||
<FileVersion>$(Version)</FileVersion> | ||
<AssemblyVersion>$(VersionPrefix).*</AssemblyVersion> | ||
<Deterministic>false</Deterministic> | ||
<OutputPath>..\..\Bin\RpcServer</OutputPath> | ||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<LangVersion>latest</LangVersion> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="NewLife.Redis" Version="5.6.2024.101" /> | ||
<PackageReference Include="NewLife.Stardust" Version="2.9.2024.101" /> | ||
<PackageReference Include="NewLife.XCode" Version="11.11.2024.402" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\NewLife.Remoting\NewLife.Remoting.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Oops, something went wrong.