TypeScript Protocol Basic_Components - samchon/framework GitHub Wiki

Basic Components

Basic Compoenents are the smallest unit of network communication in this Samchon Framework. With Basic Components, you can construct any type of network system, even how the network system is enormously scaled and complicated, by just combinating the Basic Components.

All the system templates in this framework are also being implemented by utilization of the Basic Components.

Note that, whatever the network system what you've to construct is, just concentrate on role of each system and attach matched Basic Component to the role, within framework of the Object-Oriented Design. Then construction of the network system will be much easier.

References

Class Diagram

Protocol - Basic Components

API Documents

Source Codes

IServer

IServer is used to open a server. First, extends one of them, who are derived from the IServer.

/// <reference path="../typings/samchon-framework/samchon-framework.d.ts" />

import samchon = require("samchon-framework");
import protocol = samchon.protocol;

class MyServer extends protocol.WebServer
{
	// OVERRIDE TO DEFINE WHAT TO DO WHEN A CLIENT HAS CONNECTED
	// 
	// @param driver A COMMUNICATOR WITH CONNECTED CLIENT
	public addCliet(driver: IClientDriver): void
	{
		// DO SOMETHING
	}
}
var server: MyServer = new MyServer();
server.open(54321); // OPEN SERVER
server.close(); // ALSO, CLOSING IS POSSIBLE

After inheritance, override IServer.addClient() method to defined what to do whenever a client has newly connected. To open the server, call IServer.open() method.

If you're under embarassed situation, unable to extends one of them (Server, WebServer and SharedWorkerServer) because your class already extended another one, then use IServerBase.

IServerBase

The easiest way to defning a server class is to extending one of them, who are derived from the IServer.

However, it is impossible (that is, if the class is already extending another class), you can instead implement the IServer interface, create an IServerBase member, and wrtie simple hooks to route calls into the aggregated IServerBase.

Those classes are derived from the IServerBase interface and specifying each network protocol.

Code under below is an example using the WebServerBase when extending WebServer is impossible. The example implemented IServer instead and hooked to aggregated WebServerBase.

/// <reference path="typings/samchon-framework/samchon-framework.d.ts" />

import samchon = require("samchon-framework");
import protocol = samchon.protocol;

class MySlaveServer extends protocol.external.ExternalSystem 
	implements IServer
{
	// TARGET TO HOOK
	private server_base: protocol.IServerBase;
	
	public constructor()
	{
		super();
		this.server_base = new protocol.WebServerBase();
	}
	
	/* ---------------------------------------------------
		HOOKINGS - METHODS OF ISERVER
	--------------------------------------------------- */
	public addClient(driver: protocol.IClientDriver): void
	{
		// WHAT TO DO WHEN A CLIENT HAS CONNECTED
		this.communicator = driver;
		driver.listen(this);
	}
	public open(port: number): void
	{
		this.server_base.open(port);
	}
	public close(): void
	{
		this.server_base.close();
	}
}

Also, many of modules even in Samchon Framework are using the strategy pattern because they've already extended another classes. Below classes are such things.

ICommunicator

ICommunicator takes full charge of network communication with external, conneted system. Type of the ICommunicator is specified to IClientDriver and IServerConnector whether the connected system is a server (that I've to connect) or a client (a client connected to my server)

Whenever ICommunicator network message has come from the connceted system, the network message will be converted to an object and it will be shifted to the ICommunicator.listener's replyData() method.

interface ICommmunicator
{
	private socket: SomeSocketClass;

	// LISTENER LISTENS INVOKE MESSAGE BY IT'S IProtocol.replyData() METHOD
	protected listener: IProtocol;
	
	// YOU CAN DETECT DISCONNECTION BY ENROLLING FUNCTION POINTER TO HERE.
	public onClose: Function;
	
	public sendData(invoke: Invoke): void
	{
		this.socket.write(invoke);
	}
	public replyData(invoke: Invoke): void
	{
		// WHENEVER COMMUNICATOR GETS MESSAGE, THEN SHIFT IT TO LISTENER'S replyData() METHOD.
		this.listener.replyData(invoke);
	}
}

IClientDriver

IClientDriver is a type of ICommunicator, specified for communication with external client, connected to this server. This IClientDriver is created in IServer and delivered from IServer.addClient(). Those are derived classes from the IClientDriver, being created by IServer object.

Derived Type Crated By
ClientDriver Server
WebClientDriver Server
SharedWorkerClientDriver Server

When you got the IClientDriver object in the IServer.addClient(), then specify listener from IClientDriver.listen() method.

/// <reference path="../typings/typescript-stl/typescript-stl.d.ts" />
/// <reference path="../typings/samchon-framework/samchon-framework.d.ts" />

// IMPORTS
import std = require("typescript-stl");
import samchon = require("samchon-framework");

// SHORTCUTS
import library = samchon.library;
import protocol = samchon.protocol;

class CalculatorServer extends protocol.Server
{
	private clients: std.HashSet<CalculatorClient>;
	
	// WHEN A CLIENT HAS CONNECTED
	public addClient(driver: IClientDriver): void
	{
		let client: CalculatorClient = new CalculatorClient(this, driver);
		this.clients.insert(client);
	}
}

class CalculatorClient extends protocol.IProtocol
{
	// PARENT SERVER INSTANCE
	private server: CalculatorServer;

	// COMMUNICATOR, SENDS AND RECEIVES NETWORK MESSAGE WITH CONNECTED CLIENT
	private driver: protocol.IClientDriver;

	/////
	// CONSTRUCTORS
	/////
	public constructor(server: CalculatorServer, driver: protocol.IClientDriver)
	{
		this.server = server;
		this.driver = driver;

		// START LISTENING AND RESPOND CLOSING EVENT
		this.driver.listen(this); // INVOKE MESSAGE WILL COME TO HERE
		this.driver.onClose = this.destructor.bind(this); // DISCONNECTED HANDLER
	}
	public destructor(): void
	{
		// WHEN DISCONNECTED, THEN ERASE THIS OBJECT FROM CalculatorServer.clients.
		this.server["clients"].erase(this);
	}
	
	/////
	// INVOKE MESSAGE CHAIN
	/////
	public sendData(invoke: protocol.Invoke): void
	{
		// CALL ICommunicator.sendData(), WHO PHYSICALLY SEND NETWORK MESSAGE
		this.driver.sendData(invoke);
	}
	public replyData(invoke: protocol.Invoke): void
	{
		// FIND MATCHED MEMBER FUNCTION NAMED EQUAL TO THE invoke.getListener()
		invoke.apply(this);
	}
}

IServerConnector

IServerConnector is a type of ICommunicator, specified for a client who connecting to an external server. Those are derived type from this interface IServerConnector.

To utilize this IServerConnector, create derived type with listener. constructor(listener: IProtocol). After creation, call IServerConnector.connect() with specified ip address and port number.

/// <reference path="../typings/samchon-framework/samchon-framework.d.ts" />

import samchon = require("samchon-framework");
import protocol = samchon.protocol;

class CalculatorApplication implements protocol.IProtocol
{
	// COMMUNICATOR, SENDS AND RECEIVES NETWORK MESSAGE WITH SERVER
	private connector: protocol.IServerConnector;

	/////
	// CONSTRUCTORS
	/////
	public constructor()
	{
		// CONSTRUCT CONNECTOR AND
		this.connector = new protocol.ServerConnector(this);
		this.connector.onConnect = this.handleConnect.bind(this);

		// CONNECT TO CALCULATOR-SERVER
		this.connector.connect("127.0.0.1", 17823);
	}
	private handleConnect(): void
	{
		// DO SOMETHING
		...
	}
	
	/////
	// SEND & REPLY DATA
	/////
	public sendData(invoke: protocol.Invoke): void
	{
		// CALL ICommunicator.sendData(), WHO PHYSICALLY SEND NETWORK MESSAGE
		this.connector.sendData(invoke);
	}
	public replyData(invoke: protocol.Invoke): void
	{
		// FIND MATCHED MEMBER FUNCTION IN this OBJECT AND CALL IT.
		invoke.apply(this);
	}

IProtocol

IProtocol is an interface for Invoke message, which is standard message of network I/O in Samchon Framework, chain. The IProtocol interface is used to network drivers (Basic Components) and some related classes with the network drivers, which are in a relationship of Chain of Responsibility with those network drivers.

Implements IProtocol if the class sends and handles Invoke message. Looking around source codes of Samchon Framework, especially System Templates, you can find out that all the classes and modules handling Invoke message are always implementing the IProtocol. Yes, IProtocol, this is the main role you've to follow in Samchon Framework.

Below pseudo code represents Service Module, who can build a cloud server. All the classes in the pseudo code are implementing the IProtocol because all of them are handling Invoke messages.

  • Server: Represents a server literally.
  • User: Represents an user being identified by its session id. User contains multiple Client objects.
    • In browser, an user can open multiple windows
      • User: A browser (like IE, Chrome and Safari)
      • Client: An internet browser window
  • Client: Represents a browser window and it takes role of network commmunication.
  • Service: Represents a service, domain logic.

Service Module

/// <reference path="../typings/typescript-stl/typescript-stl.d.ts" />
/// <reference path="../typings/samchon-framework/samchon-framework.d.ts" />

// IMPORTS
import std = require("typescript-stl");
import samchon = require("samchon-framework");

// SHORTCUTS
import library = samchon.library;
import collection = samchon.collection;
import protocol = samchon.protocol;

namespace service
{
	export class Server extends protocol.WebServer implements IProtocol
	{
		// SERVER HAS MULTIPLE USER OBJECTS
		private session_map: std.HashMap<string, User>;
		
		/////
		// MESSAGE CHAIN
		/////
		public sendData(invoke: protocol.Invoke): void
		{
			// SEND INVOKE MESSAGE TO ALL USER OBJECTS
			for (let it = this.session_map.begin(); !it.equal_to(this.session_map.end()); it = it.next())
				it.second.sendData(invoke);
		}
		public replyData(invoke: protocol.Invoke): void
		{
			invoke.apply(this); // HANDLE INVOKE MESSAGE BY ITSELF
		}
	}
	
	export class User extends 
		collection.HashMapCollection<number, Client> // USER HAS MULTIPLE CLIENT OBJECTS
		implements IProtocol
	{
		private server: Server; // USER REFRES SERVER
		
		/////
		// MESSAGE CHAIN
		/////
		public sendData(invoke: protocol.Invoke): void
		{
			// SEND INVOKE MESSAGE TO ALL CLIENT OBJECTS
			for (let it = this.begin(); !it.equal_to(this.end()); it = it.next())
				it.second.sendData(invoke);
		}
		public replyData(invoke: protocol.Invoke): void
		{
			invoke.apply(this); // HANDLE INOVKE MESSAGE BY ITSELF
			this.server.replyData(invoke); // OR VIA SERVER
		}
	}
	
	export class Client implements IProtocol
	{
		private user: User; // CLIENT REFERS USER
		private service: Service; // CLIENT HAS A SERVICE OBJECT
		
		private driver: WebClientDriver;
		
		/////
		// MESSAGE CHAIN
		/////
		public sendData(invoke: protocol.Invoke): void
		{
			// SEND INVOKE MESSAGE VIA driver: WebClientDriver
			this.driver.sendData(invoke);
		}
		public replyData(invoke: protocol.Invoke): void
		{
			invoke.apply(this); // HANDLE INOVKE MEESAGE BY ITSELF
			this.user.replyData(invoke); // OR VIA USER

			if (this.service != null) // OR VIA SERVICE
				this.service.replyData(invoke);
		}
	}
	
	export class Service implements IProtocol
	{
		private client: Client; // SERVICE REFRES CLIENT
		
		/////
		// MESSAGE CHAIN
		/////
		public sendData(invoke: protocol.Invoke): void
		{
			// SEND INVOKE MESSAGE VIA CLIENT
			return this.client.sendData(invoke);
		}
		public replyData(invoke: protocol.Invoke): void
		{
			invoke.apply(this); // HANDLE INVOKE MESSAGE BY ITSELF
		}
	}

Example Code

System Templates

Learning and understanding Basic Components of Samchon Framework, reading source codes and designs of System Templates' modules will be very helpful.

Name Source Documents
Cloud Service protocol/service API, Guidance
External System protocol/external API, Guidance
Parallel System protocol/parallel API, Guidance
Distributed System protocol/distributed API, Guidance
Slave System protocol/slave API, Guidance

Example Projects