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.
- A system is server, then use IServer or IServerBase.
- A server wants to handle a client has connected, then use IClientDriver.
- A system is a client conneting to an extenral server, then use IServerConnector.
References
Class Diagram
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
- In browser, an user can open multiple windows
- Client: Represents a browser window and it takes role of network commmunication.
- Service: Represents a service, domain logic.
/// <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 |