Phil edited this page Feb 20, 2018 · 27 revisions

This document is for version 1.1.18+

Table of Contents:

The Vaser API and reference catalog can be found here.

Important: Please look at my other project VaserChat for a live vaser demo application!

Click on this link for a live demo: VaserChatv1.1.7.zip or ClickOnce setup.exe App

VaserChat Login

VaserChat Main Form

New Features:

  • Event based communication
  • added “OnEmptyBuffer” event on links
  • QoS packet priority
  • “Portal.Finalize()” is now obsolete
  • Added packet dispacher
  • Added Xamarin iOS Support
  • Added NetCore Support
  • Added Unity Support

Planned Features:

  • a better wikisite
  • the release of the file transfer and content delivery library

Overview of vaser:

how vaser works

Using directives:

using Vaser; // for normal networking usage
using Vaser.OON; // advanced functionality for request/response pattern and data channeling
using Vaser.ConnectionSettings; // contains the connection settings classes

Build a container:

// Build your container for transmitting your data 
// One message is limited to 65000 bytes
// Note that your container needs an ID for identifying which one is used
// For sending you create a new instance and giving the container to a portal
public class TestContainer : Container
{
   // be careful by using write protected 'const' container IDs for 'switch', do not use 'public'
   internal const ushort myContainerID = 1;

   // Only public, non-static and standard datatypes can be transmitted
   public string message = "default message";

   // Also 1D arrays are possible
   public int[] array = new int[1000];
}

Event handling functions:

When a Client connects to a Server, Vaser raises standard Events like 'on new connection', 'on disconnect' or when the buffer of the sending queue is empty.

// Use for every function a separate container
TestContainer con4 = new TestContainer();
static void OnNewLink(object p, LinkEventArgs e)
{
   Console.WriteLine("Client connected from IP: " + e.lnk.IPv4Address);

   // Delegate a function if the buffer of the link is empty
   // see at “Send a message” for more details
   e.lnk.EmptyBuffer += OnEmptyBuffer;

   //To do: add the link to your connected client list

   // you can attach a custom ID and an object the link
   // create your own client class and attach it to the link
   // Note: Vaser has no client class, this is an example
   Client myClient = new Client();
   myClient.lnk = e.lnk; // attach the link to the client class
   e.lnk.AttachedID = myID;
   e.lnk.AttachedObject = myClient;

   // new links needs to be accepted
   e.lnk.Accept();
}

// Use for every function a separate container
TestContainer con5 = new TestContainer();
static void OnDisconnectingLink(object p, LinkEventArgs e)
{
   Console.WriteLine("Client disconnected from IP: " + e.lnk.IPv4Address);
   
   // for exemple: you can get a custom attached object from your link
   Client myClient = (Client)e.lnk.AttachedObject;
}

// Use for every function a separate container
TestContainer con6 = new TestContainer();
static void OnEmptyBuffer(object p, LinkEventArgs e)
{
   // Warning: operate threadsafe here!
   Console.WriteLine("OnEmptyBuffer called!");
}

Initialize a portal collection:

The portals are attached to the data processing methods.

// Before a server or a client can be created, you need a portal collection and portals
// delegate your data processing function to the portal event handler
// Note: The Portal ID is the priority of the QoS management. Please set all file transfers on ID 255!
static Portal system = null;
static Portal login = null;
static Portal files = null;
static PortalCollection PColl = null;

static void CreatePortalCollection()
{
   system = new Portal(100); // Portal ID 100 - first priority
   system.IncomingPacket += OnSystemPacket;

   login = new Portal(101); // Portal ID 101 - second priority
   login.IncomingPacket += OnLoginPacket;

   files = new Portal(255); // Portal ID 255 - last priority
   files.IncomingPacket += OnFilesPacket;

   PColl = new PortalCollection(); // The portal collection
   // portals can be used with multiple collections
   PColl.RegisterPortal(system);
   PColl.RegisterPortal(login);
   PColl.RegisterPortal(files);
}

// Use for every function a separate container
TestContainer con1 = new TestContainer();
static void OnSystemPacket(object p, PacketEventArgs e)
{
   // ToDo

   // for exemple: you can get a custom attached object from your link
   Client myClient = (Client)e.lnk.AttachedObject;
}

// Use for every function a separate container
TestContainer con2 = new TestContainer();
static void OnLoginPacket(object p, PacketEventArgs e)
{
   // ToDo
}

// Use for every function a separate container
TestContainer con3 = new TestContainer();
static void OnFilesPacket(object p, PacketEventArgs e)
{
   // ToDo
}

Start the server:

// Start the server
// The Server is now listen on port 1000 on all adapters.
// The stream is secured and encrypted by Kerberos. More info at: https://msdn.microsoft.com/en-us/library/bb742516.aspx
// Typical used in Domain infrastructures.
//   Supported Modes:
//    - Not Encrypted
//    - Kerberos
//    - SSL TLS 1.2
// Portal Collection: the collection you have created
static VaserKerberosServer vkerberos = null;
static VaserServer Server = null;

static void StartServer()
{
   CreatePortalCollection();

   vkerberos = new VaserKerberosServer();
   Server = new VaserServer(System.Net.IPAddress.Any, 1000, PColl, vkerberos);

   // Delegate your action processing function to the server event handler
   Server.NewLink += OnNewLink;
   Server.DisconnectingLink += OnDisconnectingLink;

   // start the server
   Server.Start();

   Console.WriteLine("Server has started.");
   // you can now pause your console
   Console.ReadKey();
}

Connect a client:

// First, initialize the portals like on the server side
// Connect the client to the Server
//   Supported Modes:
//    - Not Encrypted
//    - Kerberos
//    - SSL TLS 1.2
// Portal Collection: the collection you have created

static Link ConnectClient(string ServerAddress, int Port)
{
   try
   {
      if(PColl == null) CreatePortalCollection();

      VaserKerberosClient ckerberos = new VaserKerberosClient();
      Link lnk = VaserClient.ConnectClient(ServerAddress, Port, PColl, ckerberos);

      // delegate your disconnecting function to the disconnecting event handler
      lnk.Disconnecting += OnDisconnectingLink;
      return lnk;
   }
   catch
   {
      MessageBox.Show("can't connect to " + ServerAddress + ":" + Port);
      return null;
   }
}

Send a message:

// Create a new container, should be reused
// Note: the container is not threadsafe
	TestContainer con = new TestContainer();
// Save the message in the container
	con.message = "transmitting a message via Vaser.";
// Send the message through the portal to the client
	system.SendContainer(link, con, 1, 1);
// Hint: the last two digits are the containerID and the objectID
// ->   system.SendContainer(link, con, containerID, objectID);
// These are the <Packet_Recv>.ContainerID and <Packet_Recv>.ObjectID on the receive side
// You can send as well empty packets for commands:
// system.SendContainer(link, null, 2, 1);

// if you want that a link rises the empty buffer event use this:
	system.SendContainer(link, null, TestContainer.myContainerID, 1, true);

Receive a message:

// a packet was send ->  system.SendContainer(link, con, containerID, objectID);

public void OnLoginPacket(object sender, PacketEventArgs e)
{
   try
   {
      // convert the attached object back
      Client c = (Client)e.lnk.AttachedObject;

      // assign your used container
      switch (e.pak.ContainerID)
      {
         case TestContainer.myContainerID: // packet ID 1
            // To do: packet logic here

            // try to decrypt the incoming packet
            TestContainer con = new TestContainer(); // Better to use an existing container
            if(con.UnpackContainer(e.pak)) // Is true if the decode of the packet was successful
            {
               Console.WriteLine(con.message);
            } // maybe on false disconnect the client?
            
            break;
      }
   }
   catch
   {
      // On any error, disconnect the client
      e.lnk.Dispose();
   }
}

Disconnect a client:

lnk.Dispose();

Stoping a Server:

// Stops the server
Server.Stop();

Reqeust/response pattern

Request receive class on the server side:

using System;
using Vaser;
using Vaser.OON;

namespace test_server
{
    public class TestRequest : cRequest
    {
        TestContainer con1 = new TestContainer();
        public override void IncomingRequest(object p, PacketEventArgs e)
        {
            if (con1.UnpackContainer(e.pak))
            {
                Console.WriteLine(con1.test);
                con1.test = "Hello Back!";

                RequestResponse(con1);
            }
            else
            {
                RequestResponse(null);
            }
        }
    }
}

Response send and receive class on the client side:

using System;
using Vaser;
using Vaser.OON;

namespace test_client
{
    public class TestRequest : cRequest
    {
        TestContainer con1 = new TestContainer();
        public cStatus myRequestStarter(string myMessage, Link lnk)
        {
            con1.test = myMessage;

            return StartRequest(lnk, con1);
        }

        TestContainer con2 = new TestContainer();
        public override void RequestResult(object p, PacketEventArgs e)
        {
            if (con2.UnpackContainer(e.pak))
            {
                Console.WriteLine(con2.test);

                SetDone("myResult");
            }
            else
            {
                SetError("Decode error.");
            }
        }

    }
}

Register the request at the PortalCollection, same goes for the channeling:

    Portal system = new Portal(100);
    PortalCollection PC = new PortalCollection();
    PC.RegisterPortal(system);
    system.IncomingPacket += OnSystemPacket;

    TestRequest myRequest = new TestRequest();
    PC.RegisterRequest(myRequest, system, 501);

    TestChannel myChannel = new TestChannel();
    PC.RegisterChannel(myChannel, system, 502);

    // ... start your server here...

    // usage:
    cStatus requestStatus = myRequest.myRequestStarter("Hello World!", clientLink);
    requestStatus.Wait();
    Console.WriteLine((string)requestStatus.ResultObject);

Channel pattern

Server side:

using System;
using Vaser;
using Vaser.OON;

namespace test_server
{
    public class TestChannel : cChannel
    {
        TestContainer con1 = new TestContainer();
        public void mySendStarter(string myMessage, Link lnk)
        {
            con1.test = myMessage;

            SendPacket(con1, lnk);
        }

        TestContainer con2 = new TestContainer();
        public override void IncomingPacket(object p, PacketEventArgs e)
        {
            if (con2.UnpackContainer(e.pak))
            {
                Console.WriteLine(con2.test);
                con2.test = "Hello Back channel!";

                SendPacket(con2);
            }
            else
            {
                Console.WriteLine("Decode error!");
            }
        }
    }
}

On the client side:

using System;
using Vaser;
using Vaser.OON;

namespace test_client
{
    public class TestChannel : cChannel
    {
        TestContainer con1 = new TestContainer();
        public void mySendStarter(string myMessage, Link lnk)
        {
            con1.test = myMessage;

            SendPacket(con1, lnk);
        }

        TestContainer con2 = new TestContainer();
        public override void IncomingPacket(object p, PacketEventArgs e)
        {
            if (con2.UnpackContainer(e.pak))
            {
                Console.WriteLine(con2.test);

            }
            else
            {
                Console.WriteLine("Decode error!");
            }
        }

    }
}
Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.