Skip to content

Akronae/Iris

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

21 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Iris

Modern reliable UDP framework for .NET & Mono.

Documentation

Basic

public class EchoUdpClient : NetworkUdpClient<EndPointConnection>
{
    public EchoUdpClient (NetworkUdpClientConfiguration<EndPointConnection> config) : base(config)
    {
    }
    
    protected override EndPointConnection CreateEndPointConnection (IPEndPoint ipEndPoint)
    {
        return new EndPointConnection(ipEndPoint);
    }
    
    protected override void OnDataReceive (byte[] data, IPEndPoint endPoint)
    {
        var received = Encoding.ASCII.GetString(data);
        Console.WriteLine($"{endPoint} sent {received}");

        if (received.EndsWith("\n")) return;
        
        Send(Encoding.ASCII.GetBytes(received + "\n"), endPoint);
    }
}

const int serverPort = 8080;

// The first argument is the default endpoint which is used as receiver if `server.Send` is called
// without endpoint argument. Being a server, there is no default endpoint.
// Second is the client name, which is used for logging.
var serverConfig = new NetworkUdpClientConfiguration<EndPointConnection
{
    ServerName = "UDP Server",
    ListenPort = serverPort
};
var server = new EchoUdpClient(serverConfig);

var endPoint = new EndPointConnection(new IPEndPoint(IPAddress.Parse("127.0.0.1"), serverPort));
var clientConfig = new NetworkUdpClientConfiguration<EndPointConnection>
{
    DefaultEndPoint = endPoint,
    ServerName = "UDP Client",
};
var client = new EchoUdpClient(clientConfig);

client.Send(Encoding.ASCII.GetBytes("Hello server!"));

// Prevent the thread on which the server is running from terminating.
server.WaitHandle.WaitOne();

/**
OUTPUT:
127.0.0.1:49663 sent Hello server!
127.0.0.1:8080 sent Hello server!
**/

Using Packets

// Now inherits from `PacketUdpClient` which handles packets instead of `NetworkUdpClient`.
public class EchoUdpClient : PacketUdpClient<PacketEndPointConnection>
{
    public EchoUdpClient (PacketUdpClientConfiguration<PacketEndPointConnection> config) : base(config)
    {
    }
    
    protected override PacketEndPointConnection CreateEndPointConnection (IPEndPoint ipEndPoint)
    {
        return new PacketEndPointConnection(ipEndPoint);
    }

    protected override void OnPacketReceived (byte[] rawPacket, Packet packet, IPEndPoint endPoint)
    {
        base.OnPacketReceived(rawPacket, packet, endPoint);

        if (!(packet is MessagePacket mp)) return;

        var sender = GetClientByIpEndPointOrDefault(endPoint);
        Console.WriteLine($"{endPoint} sent {mp.Message}");

        if (!mp.Message.EndsWith("\n"))
        {
            Send(new MessagePacket(mp.Message + "\n"), sender);
        }
    }
}

// The first argument is a unique packet ID inside a protocol ID (second argument).
[Packet(100, 0)]
[PacketReliability(PacketReliability.SendTwice | PacketReliability.MustBeAcknowledged)]
public class MessagePacket : Packet
{
    [SerializedMember(0)]
    public string Message;

    public MessagePacket (string message)
    {
        Message = message;
    }

    // As long as there constructors in packets, there must be an empty constructor for the packet to be
    // instantiated by reflection during deserialization.
    public MessagePacket ()
    {
    }
}

const int serverPort = 8080;
// A `PacketUdpClient` needs to know which packets are referenced for deserializing.
var protocolAssembly = typeof(MessagePacket).Assembly;

var serverConfig = new PacketUdpClientConfiguration<PacketEndPointConnection>
{
    ServerName = "UDP Server",
    ListenPort = serverPort
}.AddProtocolAssembly(protocolAssembly);
var server = new EchoUdpClient(serverConfig);

var endPoint = new PacketEndPointConnection(new IPEndPoint(IPAddress.Parse("127.0.0.1"), serverPort));
var clientConfig = new PacketUdpClientConfiguration<PacketEndPointConnection>
{
    DefaultEndPoint = endPoint,
    ServerName = "UDP Client",
}.AddProtocolAssembly(protocolAssembly);
var client = new EchoUdpClient(clientConfig);

client.Send(new MessagePacket("Hey server!"));

server.WaitHandle.WaitOne();

/**
OUTPUT:
127.0.0.1:50711 (Id 54152) sent Hey server!
127.0.0.1:8080 (Id 65611) sent Hey server!

[UPD Server]: Requested 127.0.0.1:50711 (Id 54152) to acknowledge packet MessagePacket (0)
UDP Client acknowledged packet number 0 to 127.0.0.1:8080 (Id 65611)
127.0.0.1:50711 (Id 54152) acknowledged packet number 0
[UDP Client]: Requested 127.0.0.1:8080 (Id 65611) to acknowledge packet MessagePacket (0)
UPD Server acknowledged packet number 0 to 127.0.0.1:50711 (Id 54152)
127.0.0.1:8080 (Id 65611) acknowledged packet number 0
**/

Using Frames

public class MessageFrame : Frame<PacketUdpClient<PacketEndPointConnection>, PacketEndPointConnection>
{
    public MessageFrame (PacketUdpClient<PacketEndPointConnection> server) : base(server)
    {
    }
    
    // This handler will always be called because it is protected with `ConnectionState.All`.
    // The connection state is set on `sender.ConnectionState`.
    // The class `ConnectionState` can be inherited to create custom states,
    // be careful though to not define new states on values already taken by `ConnectionState`. 
    [PacketHandler(ConnectionState.All)]
    public void HandleMessagePacket (MessagePacket packet, PacketEndPointConnection sender)
    {
        LogUtils.Log($"{sender} sent {packet.Message}");
        
        if (!packet.Message.EndsWith("\n"))
        {
            Connection.Send(new MessagePacket(packet.Message + "\n"), sender);
        }
    }
}

public class EchoUdpClient : PacketUdpClient<PacketEndPointConnection>
{
    public EchoUdpClient (PacketUdpClientConfiguration<PacketEndPointConnection> config) : base(config)
    {
        // Each frame need to be instantiated by the client which is supposed to receive the packets.
        new MessageFrame(this);
    }
    
    protected override PacketEndPointConnection CreateEndPointConnection (IPEndPoint ipEndPoint)
    {
        return new PacketEndPointConnection(ipEndPoint);
    }
}

[Packet(100, 0)]
public class MessagePacket : Packet
{
    [SerializedMember(0)]
    public string Message;

    public MessagePacket (string message)
    {
        Message = message;
    }

    public MessagePacket ()
    {
    }
}

const int serverPort = 8080;
var protocolAssembly = typeof(MessagePacket).Assembly;

var serverConfig = new PacketUdpClientConfiguration<PacketEndPointConnection>
{
    ServerName = "UDP Server",
    ListenPort = serverPort
}.AddProtocolAssembly(protocolAssembly);
var server = new EchoUdpClient(serverConfig);

var endPoint = new PacketEndPointConnection(new IPEndPoint(IPAddress.Parse("127.0.0.1"), serverPort));
var clientConfig = new PacketUdpClientConfiguration<PacketEndPointConnection>
{
    DefaultEndPoint = endPoint,
    ServerName = "UDP Client",
}.AddProtocolAssembly(protocolAssembly);
var client = new EchoUdpClient(clientConfig);

client.Send(new MessagePacket("Hey server!"));

server.WaitHandle.WaitOne();

/**
OUTPUT:
127.0.0.1:59899 (Id 47322) sent Hey server!
127.0.0.1:8080 (Id 90471) sent Hey server!
**/

About

Modern reliable UDP framework for .NET & Mono. πŸ“‘

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages