Project

General

Profile

Channel environment and server in Scol » History » Revision 2

Revision 1 (iri, 09/25/2012 12:58 AM) → Revision 2/3 (iri, 09/25/2012 01:00 AM)

h1. Channel environment and server in Scol 

 {{toc}} 

 A channel is a pair : an environment and a network connection. 
 The network connection is mostly a TCP/IP socket connection, UDP sometimes. However, a channel can contain no network conenction : in this case, the channel is named unplugged. But a channel always has an environment. The network connection is managed by Scol itself, not by the developer. 

 In each VM, there is one channel (or more), the first channel is always unplugged, it is automatically created and, initially, gets the minimal environment. If this first channel is destroyed, the VM is destroyed. 
 A second channel is created between this new VM and the primary VM (or mother, or ScolEngine or Supervisor ... it is the same thing), except if it is the primary VM ! The new VM is destroyed if this channel is destroyed. 
 If the channel of the mother is destroyed, all VMs are destroyed. 
 (cf socketLife) 

 An environment is a list of functions (and thus variables and other objects). It is never empty. 
 Initially, all environment is the minimal environment : only all loaded Scol APIs. 
 The loaded APIs are defined in the usm.ini file of each client (machine). 

 Each added package is loaded in the current environment (one who is in the channel used for loading). Thus, a package can refer to the functions and variables previously loaded. The minimal environment is at the end of the list. The last loaded package is at the head. 

 Example : 
 we have a launcher : 
 <pre> 
 _load "dir/package_3.pkg" 
 _load "dir/package_2.pkg" 
 _load "dir/package_1.pkg" 
 main 
 </pre> 

 In the list (the environment), we get : 

 @package_3 :: package_2 :: package_1 :: minimal environment :: nil@ 

 The application can access to a function declared in package_1 from the package_1, 2 and 3. 
 The same application can access to a function declared in package_3 from the package_3 only. 

 A VM can manage several environment simultaneously. That is why this is important to know in which environment an object is created or used. The Scol function _channel returns the first created channel when a VM starts. Then, it is in this channel that you will mostly code. 

 Two environments in two differents channel can have a common part : they share several functions and variables. You can change the environment in any channel, get it, remove it, ... Two channels can have the same environment. 
 This is important to discern the diffrence between channel and environment. 

 So, in "Openspace3d":http://www.openspace3d.com (a free software written in Scol), each plugIT has its channel and its environment. All these environments are identical (functions and variables of Openspace3d + minimal environment) except the last loaded packages : the specific code of each plugIT. 

 Basically, in a client-server application, the client VM and the server VM have their channel. The client has also a channel to the server. The server has N more channel if N clients are connected. 

 That is important to order correctly the loading of packages. 

 You could read a log file : first, the differents APIs are loaded, as defined in usm.ini (and the same order). Next, each line of the launcher is loaded. 

 The channel Scol type is *Chn*. 
 The environment Scol type is *Env*. 
 The server Scol type is *Srv*. 


 h2. How to get an environment ? 

 By the Scol function *_envchannel*. It returns the environment (Env) : 

 @_envchannel <channel>@ 

 <channel> : the channel whose you want to have the environment 


 h2. How to set an environment ? 

 After its creation, it is possible to change the environment from any channel. 

 @_setenv <channel> <new_environment>@ 

 If <new_environment> is nil, this will be the minimal environment. 


 h2. How to remove the last environment ? 

 An environment is a list. To remove the last one (you find it in the first element of the list) : 

 @_removepkg <environment>@ 
 This function returns the "sub-environment" (the same list less the first element). 
 Next, change the environment in the channel : 
 @_setenv <channel> <sub_environment>@ 

 h3.Example : 

 this function removes the last package in the current channel 

 <pre> 
 fun removeTheLastPackageInTheCurrentChannel ()= 
	 let _envchannel _channel -> currentEnv in 
	 _setenv _channel _removepkg currentEnv; 
	 0;; 	
 </pre> 


 h2. How to list an environment ? 

 <pre> 
 fun getPackageNames (env)= 
 	 if env == nil then 
		  nil 
 	 else  
 	 ( 
 		 _fooS _envfirstname env; 	
 		 getPackageNames _removepkg env 
 	 );; 
 		
 fun main ()= 
	 _showconsole; 
	 getPackageNames _envchannel _channel; 
	 0;; 
 </pre> 


 h2. How to create a channel ? 

 By default, a channel is always created when a new VM is initialized. 
 If you want more, you have *_openchannel* or *_setUDP*. 

 h3. _openchannel 

 *_openchannel* creates a new channel with a TCP/IP socket. It takes three arguments : 
 * an IP address:port, like "123.123.210.12:1234". If nil then the channel will be *unplugged* (without network connection) 
 * a script to execute once the creation done. The script is like a *.scol. 
 * an inherited environment. If nil then it will be the minimal environment. 

 This function is asynchronous. It returns immediately even if the connection is not done. When the connection is active, Scol searches in the application code a function named *_connected*. If found, _connected will be executed, otherwise it will be ignored. See below. 

 h3. _setUDP 

 *_setUDP* creates a new channel with an UDP conenction. 
 * an inherited environment 
 * a port number 
 * a script like a *.scol. 

 These two functions return the +new+ channel. 

 h2. How to get a channel ? 

 The current channel is returned by the Scol function *_channel*. 
 The channel linking the VM to the primary VM is returned by the Scol function *_masterchannel*. 

 h2. How to close a channel ? 

 You have two near functions : *_closechannel* and *_killchannel*. In the first, all objects are destroyed but the current function continues until its end. 

 When a channel is destroyed, the network connection is closed also. Scol searches in the application code if a function named *_closed* exists. If yes, it will be executed and next the program continue, if no, the program continue normally. 

 h2. How to create and close a Scol server ? 

 To communicate, the VM should have a server : a server is able to receive a connection and calculate or evaluate the request. 

 When a channel is created to a remote VM (or another local VM), the network conenction must be ok otherwise the new channel is immediately and automatically destroyed. 

 This is very simple to create a Scol server : 

 @_setserver <environment> <port_number> <script>;@ 

 * The <environment> is the server environment : it can be the same than the application or another one. It will be inherited by each channel created from this server. 
 * The <port_number> must be opened and free. If this function returns nil, the port is probably already busy. 
 * The <script> is a (or more) packages loaded for each connection and the script is run in the new channel. 

 h3. To close a server : 

 @_closeserver <server>@ 


 h2. How to send a data in a channel ? 

 h3. On a TCP/IP channel 

 First, to send a message in a channel, the network connection must be opened. If the channel is unplugged, all messages will be ignored. 
 To receive datas, the receiver must be also a server. 

 Next, you should build a communication object (Scol type : *Comm*). 
 A communication takes the form "command argument". command is the function that the receiver should execute, argument is the data to send. 
 On the receiver, the function *must* be *__command* (with two underscores) otherwise the message will be lost ! Next, once __command found, the types of arguments are checked. If all is ok, the function is ran. The result is not sent to the primary sender. For that, you must build a new communication from the receiver to the sender this time ... 

 To build a communication, you must declare it before its use. Two ways : *defcom* and *defcomvar*. 

 Like for a variable, to declare a communication you make : 

 <pre> 
 defcom <communication_name> = <command> <data_types>;; 
 defcomvar <communication_name> = <data_types>;; // here, you can change the <command>, see below 
 </pre> 

 Next, to send a communication, you use *_on* : 

 @_on <channel> <communication_name>;@ 

 <channel> must be the channel to the receiver. This function returns 0 if success (no error occurred during the send). 

 Of course, if the receiver doesn't exist (destroyed, not yet created, etc), nothing will happen. 

 h4. h3. Example :  

 you want to send a message from Bob to Alice. 

 h5. h4. For Bob : 

 <pre> 
 defcom commToAlice = funHello I S S;; // sent datas are an integer and two strings 
 typeof chnToAlice = Chn;; 

 fun main ()= 
	 _showconsole; 
	
	 let _envchannel _channel -> myEnv in 
	 set chnToAlice = _openchannel "123.1.2.3:1234" nil myEnv; // create a channel to Alice with the same environment than Bob 
	 // do something 
	 let _on chnToAlice commToAlice [10 "This is Bob !" "I come in 5 minutes"] -> result in 
	 _fooS if result == 0 then 
				 "send OK" 
			 else 
				 "send KO"; 
	 0;; 
 </pre> 
	
	
 h5. h4. For Alice : 

 <pre> 
 typeof server = Srv;; 

 fun createServer ()= 
	 set server = _setserver _envchannel _channel 3500 nil; 
	 _fooS if server == nil then 
			 "Unable to create a server, the port is probably busy" 
		 else 
			 "Server created"; 
	 0;; 

 fun main ()= 
	 _showconsole; 
	 createServer; 
	 0;; 

 fun __funHello (integer, string_1, string_2)= 
	 _fooId integer; 
	 _fooS string_1; 
	 _fooS string_2; 
	 0;; 	
 </pre> 

 h3. on an UDP channel : 

 A communication object is also needed. There is no difference with the TCP/IP connection (see above). 

 @_sendUDP <commande> <communication_name>@ 
 or 
 @_sendUDPchn <channel_to_send> <command> <communication_name>@ 

 To know the IP of a connection, use *_channelIP*. 



 h2. _connected and _closed 

 *_connected* is automatically and immediately called when a network connection occurs. 

 By example, a Scol server has been initialized with a valid script (see above, How to create and close a Scol server ?), the server environment can contain this function. In this case, it will be called at each new connection on the server. The return value is ignored and its type can be anything. If _coonected doesn't exist in the current environment, it is ignored. 
 Don't call yourself this function. 

 *_closed* is automatically called when a network connection closes. 

 This is the same thing than _connected. 


 h2. How to control message queues ? 

 After executing the _on function, the message is put in a queue to the channel. Few Scol functions get informations about queues. 

 h2. Example : 

 Let us consider two virtual machines "Bob" and "Alice" who can communicate (send and receive messages). 
 We create a server on each machine to receive message and we create a channel from Bob to Alice. 
 In our example, we should launch Alice, next Bob because we send the message to Alice immediately (our code is simple). Thus, Alice must exist to receive the message ... 

 This full example can be browsed from the "repository":http://redmine.scolring.org/projects/tutorials/repository/show/channel_environment_server. 

	
	
 h2. Others 

 There are several functions about environment, channel and communication in the standard Scol release and in the syspack Scol library. See the "official documentation":http://www.scolring.org/files/doc_html/. 


 License : "CC-BY-SA-2.0":https://creativecommons.org/licenses/by-sa/2.0/ 
 Tutorial by iri 
 Updated by /