Protocol
On this page
Namespace: Nalix.Network.Protocols
Assembly: Nalix.Network
Protocol (public abstract partial class Protocol : IProtocol) is the abstract base class consumed by TcpListenerBase, UdpListenerBase, and WebSocketListenerBase. It defines the connection acceptance workflow (OnAccept, ValidateConnection), wire framing selection (Framing), inbound transform/opcode hooks (FrameProcessor, OpCodeExtractor), message processing (ProcessMessage, PostProcessMessage), and protocol-level error/message metrics.
Source Mapping
src/Nalix.Abstractions/Networking/Protocols/IProtocol.cssrc/Nalix.Network/Protocols/Protocol.Core.cssrc/Nalix.Network/Protocols/Protocol.PublicMethods.cssrc/Nalix.Network/Protocols/Protocol.Lifecycle.cssrc/Nalix.Network/Protocols/Protocol.Metrics.cs
Lifecycle & Message Pipeline
flowchart TD
subgraph AcceptPhase["1. Connection Acceptance (OnAccept)"]
NewConn["Accepted IConnection"] --> CheckAcc{"IsAccepting?"}
CheckAcc -->|No| Disc["connection.Disconnect()"]
CheckAcc -->|Yes| Val{"ValidateConnection(connection)?"}
Val -->|No| Disc
Val -->|Yes| Frame["connection.TCP.UseFraming(Framing)"]
Frame --> Begin["connection.TCP.BeginReceive(ct)"]
end
subgraph MessagePhase["2. Inbound Message Loop"]
Begin --> Inbound["Listener Transforms Frame via FrameProcessor"]
Inbound --> Proc["ProcessMessage(sender, args) (Abstract)"]
Proc --> Post["PostProcessMessage(sender, args)"]
Post --> Hook["OnPostProcess(args) + Increment TotalMessages"]
Hook --> Keep{"KeepConnectionOpen?"}
Keep -->|No| Disc
Keep -->|Yes| Next["Await Next Frame"]
endPublic & Protected Members
namespace Nalix.Network.Protocols;
public abstract partial class Protocol : IProtocol
{
// Abstract contracts required from derived protocols
public abstract IFrameProcessor FrameProcessor { get; }
public abstract IOpCodeExtractor OpCodeExtractor { get; }
public abstract void ProcessMessage(object? sender, IConnectionEventArgs args);
// Configurable properties
public virtual TransportFraming Framing { get; set; } = TransportFraming.UInt16LengthPrefixed;
public virtual bool KeepConnectionOpen { get; protected set; }
public bool IsAccepting { get; protected set; }
// Metrics
public ulong TotalMessages { get; }
public ulong TotalErrors { get; }
// Lifecycle & execution methods
public virtual void OnAccept(IConnection connection, CancellationToken cancellationToken = default);
public void PostProcessMessage(object? sender, IConnectionEventArgs args);
public void SetConnectionAcceptance(bool isEnabled);
// Protected extensibility hooks
protected virtual bool ValidateConnection(IConnection connection) => true;
protected virtual void OnPostProcess(IConnectionEventArgs args);
protected virtual void OnConnectionError(IConnection connection, Exception exception);
protected virtual void Dispose(bool disposing);
// Diagnostics & disposal
public virtual string GenerateReport();
public virtual void WriteReportData(Utf8JsonWriter writer);
public void Dispose();
}
Implementing a Custom Protocol
When using Nalix.Hosting (builder.MapTcp<MyProtocol>(port)), you only need to implement ProcessMessage if you inherit from the hosting protocol base or supply FrameProcessor (FramePipeline.Instance) and OpCodeExtractor (NativeOpCodeExtractor.Instance):
using Nalix.Abstractions.Networking;
using Nalix.Abstractions.Networking.Packets;
using Nalix.Abstractions.Networking.Protocols;
using Nalix.Codec.Classifiers;
using Nalix.Codec.Transforms;
using Nalix.Network.Protocols;
using Nalix.Runtime.Dispatching;
public sealed class GameProtocol(IPacketDispatch dispatcher) : Protocol
{
public override IFrameProcessor FrameProcessor => FramePipeline.Instance;
public override IOpCodeExtractor OpCodeExtractor => NativeOpCodeExtractor.Instance;
public GameProtocol(IPacketDispatch dispatcher, bool keepOpen = true) : this(dispatcher)
{
this.KeepConnectionOpen = keepOpen;
this.IsAccepting = true;
}
public override void ProcessMessage(object? sender, IConnectionEventArgs args)
{
if (args.Lease is not null)
{
dispatcher.HandlePacket(args.Lease, args.Connection);
}
}
}