GoPlay.Server
1.0.3
dotnet add package GoPlay.Server --version 1.0.3
NuGet\Install-Package GoPlay.Server -Version 1.0.3
<PackageReference Include="GoPlay.Server" Version="1.0.3" />
<PackageVersion Include="GoPlay.Server" Version="1.0.3" />
<PackageReference Include="GoPlay.Server" />
paket add GoPlay.Server --version 1.0.3
#r "nuget: GoPlay.Server, 1.0.3"
#:package GoPlay.Server@1.0.3
#addin nuget:?package=GoPlay.Server&version=1.0.3
#tool nuget:?package=GoPlay.Server&version=1.0.3
GoPlay.Net
中文版: README_zh.md
Write long-connection game servers like ASP.NET — slap an attribute on a function and clients call it like a local method.
GoPlay.Net is a C# long-connection RPC framework for real-time game servers (and any app that needs push). It takes the route model from Pomelo, the Actor model from ET / Orleans, and the attribute-routing ergonomics from ASP.NET Core, and compresses them into a pragmatic C# stack with full client code generation.
The name "GoPlay" is historical: the first implementation was in Golang; the current production-quality port lives here in C#.
Performance at a Glance
Numbers from the official BDN baseline (Intel Core i9-14900K / Windows 11, net10). Full report and regression tripwires in Frameworks/Benchmark/README.md; distilled version in Docs/en/02.performance.md · Docs/zh/02.performance.md.
| Metric | net8 LTS | net10 STS |
|---|---|---|
| Single-connection serial Echo RTT (7 B payload) | 48.13 µs | 42.24 µs |
| Serial throughput ceiling (per connection) | ~20.8 kreq/s | ~23.7 kreq/s |
Route dispatch hot path (InvokeRoute) |
146.5 ns | 97.0 ns |
| Allocation per end-to-end Echo RTT | 4.00 KB | 3.84 KB |
| Gen0 / 1k ops | 0.1221 | 0.1221 |
Concurrent Echo throughput (MaxConcurrency=64, CPU-bound) |
— | ~103k req/s |
- 50× speedup on delay-bound business via
[MaxConcurrency(N)]: adelay=10msworkload jumps from 68 req/s (serial) to 3 178 req/s (N=64). See 02.performance.md. - Zero-alloc hot path: Header + Body both encode straight into the same
IBufferWriter<byte>span; each connection allocates oneArrayBufferWriterfor its entire lifetime. - O(1) route dispatch: Routes are resolved to
uintids during handshake; runtime lookup is a singleDictionary<uint, ProcessorRunner>hop into a compiled delegate. - Compile-time safety, runtime speed: Roslyn analyzers fail the build on illegal
[MaxConcurrency]combos or cross-processor escape hatches; source generators emitProcessorRef<T>extensions that read like local calls. - Four runtimes, one codebase: net7 / net8 / net9 / net10 all pass 36/36 end-to-end tests; the client library additionally targets
netstandard2.1for Unity.
How it stacks up against other game-server stacks
Third-party positioning by Google Gemini 3.1 Pro after reading the baseline. Numbers for the other stacks are Gemini's ballpark estimates, not official figures from those projects — treat the table as a rough radar chart, not a head-to-head benchmark.
| Stack / framework type | Typical RTT | Route dispatch cost | GC pressure / allocation | Overall take |
|---|---|---|---|---|
| Traditional C++ (Skynet / Muduo) | 20 µs – 50 µs | Extremely low (function pointers) | No GC (manual) | Performance yardstick, but painful ergonomics and leak-prone |
| Mainstream Go (Leaf / Pitaya) | 100 µs – 300 µs | Medium (reflection or interfaces) | Medium (Go GC) | Great concurrency and DX, but GC jitter at ultra-low-latency scale |
| Classic C# / Java (older frameworks) | 200 µs – 500 µs | Higher (heavy reflection) | High (frequent Gen0 / Gen1) | Rapid business development, but you scale out with iron |
| GoPlay.Net (.NET 10) | 42 µs | 97 ns (extremely low) | Extremely low (pooled / Span) | C++-class performance with C# developer ergonomics |
Gemini's summary quote: "Within the managed-language camp (C# / Java / Go) it has closed in on — and in several sub-metrics matched — the ceiling of highly tuned C++ frameworks."
Full per-metric breakdown: Docs/en/02.performance.md#third-party-review-what-gemini-31-pro-said · Docs/zh/02.performance.md#第三方评价gemini-31-pro-读过基线后怎么说.
Docs
| Topic | English | 中文 |
|---|---|---|
| Getting started | en | zh |
| Performance | en | zh |
| Core concepts | en | zh |
| Processor-Actor model | en | zh |
| Transport & Encoder | en | zh |
| Tools & Code generation | en | zh |
| Clients (C# / TS / JS) | en | zh |
| Advanced topics | en | zh |
| Repository structure | en | zh |
| Wire protocol | en | zh |
Highlights
- Attribute routing:
[Processor("echo")]+[Request("request")]→ clients call"echo.request". No boilerplate dispatcher. - Processor as Actor: every processor owns a dedicated
ProcessorRunner+ FIFO mailbox; zero-lock business code by default, optional[MaxConcurrency(N)]when you need parallelism. - Safe cross-processor calls:
Server.GetProcessor<T>()+[ProcessorApi]+ a Roslyn source generator → cross-processor invocation reads like a local method but runs on the target mailbox. - Pluggable transport: TCP / NetCoreServer / WebSocket / Secure WebSocket out of the box; bring your own by implementing
TransportServerBase. - Pluggable encoder: Protobuf (default, zero-alloc hot path) and Json; swap by
EncodingType. - Full client codegen: the
goplayCLI scans your processors and emits strongly-typed client extensions (C#, TypeScript, any target via Liquid templates). - Multi-language clients: C# (desktop + Unity), TypeScript (
goplay-ws), vanilla JavaScript (build-free). - Testability: end-to-end tests look like calling local methods (see TestEcho.cs).
- Production details: graceful shutdown with drain budget, request / heartbeat timeouts, Kick frames, broadcast with back-pressure, Roslyn analyzers that fail the build on unsafe cross-processor access.
30-Second Server
[Processor("echo")]
public class EchoProcessor : ProcessorBase
{
public override string[] Pushes => new[] { "echo.push" };
[Request("request")]
public PbString Request(Header header, PbString data)
=> new PbString { Value = $"Server reply: {data.Value}" };
[Notify("notify")]
public void Notify(Header header, PbString data)
=> Push("echo.push", header, new PbString { Value = $"Server push: {data.Value}" });
}
var server = new Server<NcServer>();
server.Register(new EchoProcessor());
server.Start("*", 8888);
30-Second Client
var client = new Client<NcClient>();
await client.Connect("localhost", 8888);
// Strong-typed, generated from the server's [Request] signature
var (status, resp) = await client.Echo_Request(new PbString { Value = "Hello" });
// status.Code == StatusCode.Success
// resp.Value == "Server reply: Hello"
Full walk-through: Getting Started (EN) / 快速上手 (中文).
Install
Fastest — templates
dotnet new install GoPlay.Templates
dotnet new goplay-tcp -n MyGame # or: dotnet new goplay-ws
NuGet
dotnet add package GoPlay.Server
dotnet add package GoPlay.Core.Transport.NetCoreServer # or Transport.Ws / Transport.Wss
dotnet add package GoPlay.Client
dotnet tool install -g GoPlay.Tools # optional: goplay CLI
TypeScript client
npm install goplay-ws
NuGet Packages
| Package | Purpose | Source |
|---|---|---|
GoPlay.Core |
Protocol / Encoder / Transport base | Frameworks/Core |
GoPlay.Server |
Server, ProcessorRunner, ProcessorRef | Frameworks/Server |
GoPlay.Client |
C# client (net7+ and netstandard2.1 for Unity) | Frameworks/Client |
GoPlay.Core.Transport.NetCoreServer |
TCP transport (recommended) | Frameworks/Transport.NetCoreServer |
GoPlay.Core.Transport.Ws |
WebSocket transport | Frameworks/Transport.Ws |
GoPlay.Core.Transport.Wss |
Secure WebSocket transport | Frameworks/Transport.Wss |
GoPlay.Tools |
goplay CLI (extension/config/excel2proto) |
Tools/Main |
GoPlay.Templates |
dotnet new goplay-tcp / goplay-ws |
ProjectTemplates |
How It Compares
- vs Pomelo: same
processor.methodrouting, Request / Notify / Push triad and route map in handshake — but in statically typed C#, with per-processor Actor isolation and client codegen. - vs ET: both are C# with an Actor model; ET uses one Actor per Entity (usually per player), GoPlay uses one Actor per Processor (a feature module) — better for layered features like lobby / match / battle / DB.
- vs ASP.NET Core: same attribute-routed ergonomics, but long-connection with Push / Notify / Broadcast; processors are long-lived instances (not per-request DI scopes).
- vs Orleans: Processors are "long-lived strongly-typed grains with configurable per-Actor concurrency"; today single-node, cluster mode on the roadmap (
TO-DO.md).
Full comparison: 03.concepts.md.
Repository Map
See Docs/en/09.structure.md / Docs/zh/09.structure.md. Short version:
Frameworks/ C# framework body (Core / Server / Client / Transport*)
Clients/ TypeScript + pure-JS clients
Tools/ goplay CLI + Roslyn generator + analyzers
ProjectTemplates/ dotnet new goplay-tcp / goplay-ws templates
Docs/ en/ + zh/ topic docs (performance, concepts, protocol, ...)
Thanks
Thanks to JetBrains for providing an open source license for GoPlay.Net.
License
MIT. See LICENSE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- GoPlay.Core (>= 1.0.3)
-
net7.0
- GoPlay.Core (>= 1.0.3)
-
net8.0
- GoPlay.Core (>= 1.0.3)
-
net9.0
- GoPlay.Core (>= 1.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.3 | 87 | 4/24/2026 |
| 1.0.2 | 96 | 4/23/2026 |
| 1.0.1 | 55 | 4/22/2026 |
| 1.0.0 | 62 | 4/22/2026 |
| 0.9.1 | 85 | 4/22/2026 |
| 0.9.0 | 99 | 4/20/2026 |
| 0.2.23 | 239 | 11/12/2024 |
| 0.2.22 | 225 | 10/12/2024 |
| 0.2.21 | 218 | 10/11/2024 |
| 0.2.20 | 230 | 10/10/2024 |
| 0.2.19 | 237 | 9/14/2024 |
| 0.2.18 | 241 | 9/14/2024 |
| 0.2.17 | 214 | 7/31/2024 |
| 0.2.16 | 201 | 7/29/2024 |
| 0.2.15 | 239 | 7/2/2024 |
| 0.2.14 | 239 | 6/17/2024 |
| 0.2.13 | 243 | 6/17/2024 |
| 0.2.12 | 230 | 6/17/2024 |
| 0.2.11 | 230 | 6/17/2024 |
| 0.2.10 | 241 | 5/17/2024 |