Dignus.ActorServer
3.1.0
dotnet add package Dignus.ActorServer --version 3.1.0
NuGet\Install-Package Dignus.ActorServer -Version 3.1.0
<PackageReference Include="Dignus.ActorServer" Version="3.1.0" />
<PackageVersion Include="Dignus.ActorServer" Version="3.1.0" />
<PackageReference Include="Dignus.ActorServer" />
paket add Dignus.ActorServer --version 3.1.0
#r "nuget: Dignus.ActorServer, 3.1.0"
#:package Dignus.ActorServer@3.1.0
#addin nuget:?package=Dignus.ActorServer&version=3.1.0
#tool nuget:?package=Dignus.ActorServer&version=3.1.0
Dignus.ActorServer
High-performance actor-based network server framework.
Overview
Dignus.ActorServer combines:
- Actor-based execution (
Dignus.Actor.Core) - High-performance networking (TCP / TLS)
- Protocol-based message dispatch
Incoming network packets are decoded into actor messages and processed sequentially.
Quick Start
A minimal server consists of:
- Register protocol mappings
- Configure server options (decoder / serializer)
- Create actor system
- Implement session actor
- Implement server
- Start server
1. Protocol Registration
private static void RegisterProtocol(IServiceProvider serviceProvider)
{
var mapper = serviceProvider.GetService<ProtocolBodyTypeMapper>();
mapper.AddMapping<CreateAccountReq>(CLSProtocol.CreateAccountReq);
mapper.AddMapping<LoginReq>(CLSProtocol.LoginReq);
}
Register by Protocol Name
If the protocol enum name and message body type name are the same, mappings can be registered automatically from an assembly.
private static void RegisterProtocol(IServiceProvider serviceProvider)
{
var mapper = serviceProvider.GetService<ProtocolBodyTypeMapper>();
mapper.RegisterByProtocolName<CLSProtocol>(typeof(CreateAccountReq).Assembly);
}
For multiple assemblies:
private static void RegisterProtocol(IServiceProvider serviceProvider, IEnumerable<Assembly> assemblies)
{
var mapper = serviceProvider.GetService<ProtocolBodyTypeMapper>();
mapper.RegisterByProtocolName<CLSProtocol>(assemblies);
}
This registers body types whose type name matches a protocol enum name.
Example:
public enum CLSProtocol
{
CreateAccountReq = 1001,
LoginReq = 1002
}
public sealed class CreateAccountReq : IActorMessage
{
}
public sealed class LoginReq : IActorMessage
{
}
2. Server Setup
RegisterProtocol(serviceProvider);
var serverOptions = ServerOptions.Builder()
.UseDecoder(new PacketFramer(serviceProvider))
.UseSerializer(new MessageSerializer())
.Build();
var actorSystem = new ActorSystem();
var lobby = new LobbyServer(actorSystem, serverOptions, serviceProvider);
lobby.Start(30000);
3. Packet Decoder
internal class PacketFramer(IServiceProvider serviceProvider) : IActorMessageDecoder
{
protected const int PacketSize = sizeof(int);
protected const int ProtocolSize = sizeof(ushort);
private readonly ProtocolBodyTypeMapper _bodyTypeMapper =
serviceProvider.GetService<ProtocolBodyTypeMapper>();
public IActorMessage Deserialize(ReadOnlySpan<byte> packet)
{
int protocol = BitConverter.ToUInt16(packet[..PacketSize]);
if (_bodyTypeMapper.ContainsProtocol(protocol) == false)
return null;
var bodyString = Encoding.UTF8.GetString(packet[ProtocolSize..]);
var bodyType = _bodyTypeMapper.GetBodyType(protocol);
return (IActorMessage)JsonSerializer.Deserialize(bodyString, bodyType);
}
public bool TryFrame(ISession session, ArrayQueue<byte> buffer,
out ArraySegment<byte> packet,
out int consumedBytes)
{
packet = default;
consumedBytes = 0;
if (buffer.Count < PacketSize)
return false;
var packetSize = BitConverter.ToInt32(buffer.Peek(PacketSize));
if (buffer.Count < packetSize + PacketSize)
return false;
consumedBytes = BitConverter.ToInt32(buffer.Read(PacketSize));
return buffer.TrySlice(out packet, consumedBytes);
}
}
4. Serializer
internal class MessageSerializer : IActorMessageSerializer
{
public IActorMessage Deserialize(ArraySegment<byte> bytes)
{
return new BinaryMessage(bytes);
}
public ArraySegment<byte> MakeSendBuffer(INetworkActorMessage packet)
{
return packet is BinaryMessage msg ? msg.Data : default;
}
public ArraySegment<byte> MakeSendBuffer(IPacket packet)
{
return default;
}
}
5. Session Actor
public class PlayerActor : SessionActorBase
{
private readonly StateController _stateController;
private Player _player;
public PlayerActor(IServiceProvider serviceProvider)
{
_stateController = new StateController(this, serviceProvider);
}
protected override ValueTask OnReceive(IActorMessage message, IActorRef sender)
{
if (message is KickUserMessage kick)
{
Send(PacketFactory.MakePacket(LSCProtocol.ServerNotify, 0,
new ServerNotify { ErrorCode = kick.Reason }));
ChangeState(PlayerStateType.Disconnect);
}
else
{
return _stateController.HandleMessageAsync(message, sender);
}
return ValueTask.CompletedTask;
}
public void Send(INetworkActorMessage message)
{
NetworkSession.SendAsync(message);
}
public void Send(IPacket packet)
{
NetworkSession.SendAsync(packet);
}
}
6. Server Implementation
internal class LobbyServer(
ActorSystem actorSystem,
ServerOptions serverOptions,
IServiceProvider serviceProvider)
: TcpServerBase<PlayerActor>(actorSystem, serverOptions)
{
protected override PlayerActor CreateSessionActor()
{
var actor = new PlayerActor(serviceProvider);
actor.ChangeState(PlayerStateType.Initial);
return actor;
}
protected override void OnDeadLetterMessage(DeadLetterMessage deadLetterMessage)
{
LogHelper.Error($"{deadLetterMessage.Reason}");
if (deadLetterMessage.Reason == DeadLetterReason.ExecutionException)
{
var exceptionMessage = deadLetterMessage.Message as ActorExceptionMessage;
LogHelper.Error(exceptionMessage.Exception);
}
}
}
Execution Flow
TCP Packet
↓
Frame
↓
Deserialize (protocol → message)
↓
Actor Mailbox
↓
Actor.OnReceive
↓
Send Response
Performance
Benchmark Environment
- CPU: Intel Core i5-12400F (12th Gen)
- Cores / Threads: 6 / 12
- Max Turbo Frequency: 4.40 GHz
- Memory: 32 GB
- Runtime: .NET 10 (Release x64)
Test Conditions
- Server address: 127.0.0.1
- Server port: 5000
- Protocol: Plain TCP (no TLS)
- Working clients: 1
- In-flight messages per client: 1000
- Message size: 32 bytes
- Benchmark duration: 10 seconds
Round-Trip (TCP)
Total Time: 10.002 seconds
Total Client: 1
Total Bytes: 4,364,075,744
Total Data: 4.06 GiB
Total Message: 136,377,367
Data Throughput: 416.11 MiB/s
Message Throughput: 13,634,960 msg/s
Test Conditions
- Server address: 127.0.0.1
- Server port: 5000
- Protocol: Plain TCP (no TLS)
- Working clients: 100
- Message size: 32 bytes
- Benchmark duration: 10 seconds
Fan-out (100 clients)
Total Time: 10.008 seconds
Total Client: 100
Total Bytes: 4,909,594,848
Total Data: 4.57 GiB
Total Message: 153,424,839
Data Throughput: 467.83 MiB/s
Message Throughput: 15,329,728 msg/s
Test Conditions
- Server address: 127.0.0.1
- Server port: 5000
- Protocol: TLS over TCP
- Working clients: 1
- Message size: 32 bytes
- Benchmark duration: 10 seconds
TLS Round-Trip
Total Time: 10.011 seconds
Total Client: 1
Total Bytes: 3,531,230,304
Total Data: 3.29 GiB
Total Message: 110,350,947
Data Throughput: 336.41 MiB/s
Message Throughput: 11,023,486 msg/s
Test Conditions
- Server address: 127.0.0.1
- Server port: 5000
- Protocol: TLS over TCP
- Working clients: 100
- Message size: 32 bytes
- Benchmark duration: 10 seconds
TLS Fan-out (100 clients)
Total Time: 10.052 seconds
Total Client: 100
Total Bytes: 4,852,865,632
Total Data: 4.52 GiB
Total Message: 151,652,051
Data Throughput: 460.42 MiB/s
Message Throughput: 15,087,042 msg/s
Highlights
- 10M+ messages/sec throughput
- 300–450 MiB/s sustained throughput
- full end-to-end measurement (decode → actor → encode → send)
- no ThreadPool usage for actor execution
Architecture Overview
TcpServerBase / TlsServerBase
↓
ActorPacketProcessor
↓
SessionActor
↓
Actor
Concurrency Model
- single-threaded execution per actor
- dispatcher-based scheduling
- no shared mutable state
- message-driven processing
Protocol Model (Default)
Protocol → BodyType → Deserialize → Actor
- no handler binding
- minimal overhead
- direct actor execution
Protocol Pipeline (Advanced)
Protocol → Middleware → Handler → Actor
Use when:
- authentication required
- validation needed
- logging / filtering required
- complex execution flow needed
TCP / TLS Support
- TCP →
TcpServerBase<TActor> - TLS →
TlsServerBase<TActor>
Usage is identical except transport layer.
Summary
- Actor → business logic
- ActorSystem → execution
- Server → network entry point
- Decoder → packet parsing
- Serializer → packet writing
- Mapper → protocol resolution
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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
- Dignus.Actor.Core (>= 2.1.2)
- Dignus.Sockets (>= 2.0.3)
-
net8.0
- Dignus.Actor.Core (>= 2.1.2)
- Dignus.Sockets (>= 2.0.3)
-
net9.0
- Dignus.Actor.Core (>= 2.1.2)
- Dignus.Sockets (>= 2.0.3)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Dignus.ActorServer:
| Package | Downloads |
|---|---|
|
Dignus.Commands
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.1.0 | 134 | 5/8/2026 |
| 3.0.4 | 121 | 5/2/2026 |
| 3.0.3 | 98 | 5/2/2026 |
| 3.0.2 | 107 | 4/29/2026 |
| 3.0.1 | 103 | 4/23/2026 |
| 3.0.0 | 137 | 4/16/2026 |
| 3.0.0-preview.9 | 55 | 4/11/2026 |
| 3.0.0-preview.8 | 64 | 4/9/2026 |
| 3.0.0-preview.7 | 56 | 3/30/2026 |
| 3.0.0-preview.6 | 57 | 3/29/2026 |
| 3.0.0-preview.5 | 55 | 3/29/2026 |
| 3.0.0-preview.4 | 84 | 3/28/2026 |
| 3.0.0-preview.3 | 53 | 3/23/2026 |
| 3.0.0-preview.2 | 48 | 3/22/2026 |
| 3.0.0-preview.1 | 45 | 3/22/2026 |
| 2.0.1 | 98 | 3/21/2026 |
| 2.0.0 | 109 | 3/20/2026 |
| 1.2.3 | 113 | 3/19/2026 |
| 1.2.2 | 110 | 3/18/2026 |
| 1.2.1 | 125 | 3/15/2026 |