UDP Session
Trên trang này
Namespace: Nalix.SDK.Transport
Assembly: Nalix.SDK
UdpSession ([UnsupportedOSPlatform("browser")] public class UdpSession : TransportSession) là transport datagram có xác thực phía client trong Nalix.SDK, được xây dựng trên UdpFrameSender và UdpFrameReader.
Ánh xạ mã nguồn
src/Nalix.SDK/Transport/UdpSession.cssrc/Nalix.SDK/Transport/Internal/Udp/UdpFrameSender.cssrc/Nalix.SDK/Transport/Internal/Udp/UdpFrameReader.cssrc/Nalix.Codec/Transforms/FramePipeline.cs
Định dạng datagram có xác thực trên dây
Chiều gửi (Client $\rightarrow$ Server)
UdpFrameSender bọc mỗi gói đã được biến đổi trong một phong bì xác thực 12 byte (8-byte SessionToken prefix + 4-byte seeded XxHash32 MAC trailer):
+-----------------------------------+-----------------------------------+-----------------------------------+
| SessionToken (8B, LE UInt64) | Transformed Packet Payload | UdpMacTag (4B, LE UInt32) |
| (_state.SessionToken) | (Compressed / AEAD Encrypted) | XxHash32(Secret, seed: Hash(0..N))|
+-----------------------------------+-----------------------------------+-----------------------------------+
Bytes 0..7 Bytes 8..(dataLen - 1) Bytes dataLen..(dataLen + 3)
- Biến đổi chiều gửi: Gọi
FramePipeline.ProcessOutbound(...)để áp dụng nén LZ4 và mã hóa AEAD với số sequence 32-bit tiếp theo. - Chốt MTU: Kiểm tra
current.Length + 8 + 4 <= Options.MaxUdpDatagramSize(mặc định1400byte); némNetworkExceptionnếu vượt quá. - Tính MAC có khóa: Ghi
SessionToken(8byte) + payload đã biến đổi (current.Lengthbyte), tínhuint payloadHash = XxHash32.Compute(finalLease.SpanFull[..dataLen]), tínhuint computedTag = XxHash32.Compute(_state.Secret.AsSpan(), seed: payloadHash), rồi gắncomputedTaglàm đuôi 4 byte little-endian.
Chiều nhận (Server $\rightarrow$ Client)
UdpFrameReader xác thực mọi datagram nhận được trước khi chuyển tiếp:
- Yêu cầu
!_state.Secret.IsZerovàdatagram.Length >= PacketHeader.Size + 4. - Xác minh đuôi MAC
XxHash324 byte với_state.Secretvà loại bỏ đuôi 4 byte đó. - Chạy
FramePipeline.ProcessInbound(...)(giải mã AEAD + giải nén LZ4) và kiểm tra số sequence với_sequence.IsValid(seq, s_sequenceOptions.UdpWindow). - Chuyển payload đã xác minh tới
DispatchPendingMessage,OnMessageReceivedvàOnMessageAsync.
Tham chiếu API công khai
namespace Nalix.SDK.Transport;
[UnsupportedOSPlatform("browser")]
public class UdpSession : TransportSession
{
public UdpSession(TransportOptions options, SessionState? state = null);
public ulong SessionToken { get; set; }
public override TransportOptions Options { get; }
public override bool IsConnected { get; }
public override event EventHandler? OnConnected;
public override event EventHandler<Exception>? OnDisconnected;
public override event EventHandler<IBufferLease>? OnMessageReceived;
public override event EventHandler<Exception>? OnError;
public event Func<ReadOnlyMemory<byte>, Task>? OnMessageAsync;
public override Task ConnectAsync(string? host = null, ushort? port = null, CancellationToken ct = default);
public override Task DisconnectAsync();
public override Task SendAsync(IPacket packet, CancellationToken ct = default);
public override Task SendAsync(IPacket packet, bool? encrypt = null, CancellationToken ct = default);
public override Task SendAsync(ReadOnlyMemory<byte> payload, bool? encrypt = null, CancellationToken ct = default);
public override void ResetSequenceCounters();
}
Mô hình ghép đôi TCP + UDP (chia sẻ SessionState)
Trên máy chủ, UdpListenerBase xác thực datagram UDP dựa trên kết nối TCP đang hoạt động trong IConnectionHub (SessionToken + Secret + ghim endpoint theo LocalPort). Hãy truyền tcpSession.State khi tạo UdpSession:
using System;
using System.Threading.Tasks;
using Nalix.SDK.Options;
using Nalix.SDK.Transport;
using Nalix.SDK.Transport.Extensions;
TransportOptions options = new()
{
Address = "127.0.0.1",
Port = 57206
};
// 1. Kết nối TCP và hoàn tất handshake X25519
// Bước này điền tcp.State.Secret, tcp.State.SessionToken và tcp.State.LocalPort
using TcpSession tcp = new(options);
await tcp.ConnectAsync();
await tcp.HandshakeAsync();
// 2. Tạo UdpSession đi kèm, chia sẻ tcp.State
// UdpSession.ConnectAsync tự động bind vào tcp.State.LocalPort (ReuseAddress = true)
using UdpSession udp = new(options, tcp.State);
udp.OnMessageReceived += (_, lease) =>
{
Console.WriteLine($"Received authenticated UDP datagram ({lease.Length} bytes)");
};
await udp.ConnectAsync();
await udp.SendAsync(new PlayerInputPacket { X = 12.5f, Y = 4.0f });