Examples

TcpIp connection

12 TcpIp Connection.celsrc
-.-
Connecting to a remote system

Cells can run locally or remotely but communicate in the same way, by sending and receiving 
messages. Of course the connection with the remote system has to be established, before being 
able to communicate with cells on a remote system. The part of the virtual machine responsible 
for that is the connection manager. 

Below you can find a simple example that demonstrates how a link between two systems 
is set up and how cells on the different systems exchange messages.

In this example the send and receive side of the program are combined in one program,
so you don't have to flip from one file to another - but obviously they do not need to be 
in the same program. This example establishes a connection with itself over tcp/ip and sends 
some messages.

In order to run this program you need to know the name (or ip address) of your computer. 
On Windows you can easily get that by going to settings (window key to get the menu, select 
settings, then 'system' and then 'about'). 

The same program can be run on two interconnected computers - the only thing to change 
is the name (or ip addresses) of the systems to interconnect.

The message exchange is as follows:

Caller 									ConxMgr				Callee

Connect to Apollo on port 27524		------->
											<-------		Listen on port 27524
Connected							<-------
											------->		Accept incoming connection on 27524	
									<--------------- 		Send 'HelloThere(name)' to caller
reply 'MyNameIs(name)'				--------------->
Send 'x' messages to Callee			--------------->		Count the messages
Ask how many received 				--------------->			
									<---------------		reply nr of messages
			
Note that connecting to a remote system and exchanging messages is easy - no boiler plate code
for queueing messages, buffer management, synchronisation etc. is required. 

To run the example, compile and instantiate ConxTest.						
-.-------------------------------------------------------------------------------------------------
use Windows, Math, Strings, Editor, System

-.-
	The connection test creates two callers and two callees.
-.-
design ConxTest is

	cell Caller, Callee
	cell Creator

	constructor is 
		-- Create a window for output and set it as stdout
		system <- stdout.Set( create MenuWindow("Connecting to a remote CellSpeak system over Tcp/Ip"))
			
		-- Create two callers that will connect to a port on a remote system..
		create CallerDesign("Bob",  "Apollo","27524")
		create CallerDesign("Tim", "Apollo","27526")
		
		-- Create two callees that will listen to a port ..
		create CalleeDesign("Alice", "27524")
		create CalleeDesign("Judy", "27526")
	end
end
-.-
	The caller tries to connect to another system and sends a number of test messages
-.-
design CallerDesign( ansi Name, ansi Remote, ansi Port) is 
	cell ConxMgr				-- The connection manager cell
	cell Callee 				-- The id of the cell that replied
	keep Name, Remote, Port		-- we keep the parameters

	constructor is 	
		-- The caller needs the connection manager - the service is called "ConxMgr"
		system <- Service.Get("ConxMgr")
	end
	
	on Service.Provider(ansi Service, cell Provider) do
		-- check the service
		Service is "ConxMgr" ? ConxMgr = Provider : yield

		-- We want to set up a connection with a remote system
		ConxMgr <- TCPIP.Connect(Remote, Port)				
	end
	
	-- The connection mgr sends this message if the connection was successful (or was already established)
	on TCPIP.Connected( ConxClass Conx ) do
		-- set the protocol to be used over the connection - the last parameter is the cell that will handle the comms
		ConxMgr <- Set.Protocol( Conx, "CLSPK", self )
	
		-- print a message on the display
		system <- println("[Name]: connection [Remote] port [Port] established.")		
	end
	
	-- The following messages are handled by the 'handler' - the last parameter in the Set.Protocol message
	on CLSPK.Ready( cell Callee ) do	
		keep Callee
		
		-- Give some feedback
		system <- println("[Name]: CellSpeak protocol ready to talk to cell [Callee]")
		
		-- Send hello
		Callee <- HelloThere(Name)
		
		-- Send a nr of test messages
		for i=1 to 1000 => Callee <- TestMessage("MSG[i] 0123456789 abcdefghijklmnopqrstuvwxyz")
		
		-- ask how many received
		Callee <- HowManyReceived
	end
	
	-- The response from the callee
	on MyNameIs(ansi NameCallee) do
		system <- println("[Name]: my counterpart's name is [NameCallee]")
	end
	
	-- The Callee reports the nr of messages received
	on Received(int count, ansi CalleeName) do
		system <- println("[Name]: [CalleeName] received a total of [count] messages - closing connection")
		ConxMgr <- TCPIP.Close( Callee )	
	end
end

-.-
	The callee listens to incoming calls on a specific port and replies to requests from the caller
-.-
design CalleeDesign(ansi Name, ansi Port) is 
	cell ConxMgr, Caller
	keep Name, Port

	constructor is 
		-- The callee also needs the connection manager
		system <- Service.Get("ConxMgr")	
	end
	
	destructor is 
		-- close the connection and stop listening
		ConxMgr <- TCPIP.Stop.Listening(Port)				
	end

	on Service.Provider(ansi Service, cell Provider) do
		-- check that we have received the right service - otherwise yield
		Service is "ConxMgr" ? ConxMgr = Provider : yield
		
		-- We tell the connection manager that we want to listen for incoming cellspeak connections on a port
		ConxMgr <- TCPIP.Listen( Port )
	end
	
	-- we get a confirmation of a connection
	on TCPIP.Accept( ConxClass Conx ) do		
		-- feedback
		system <- println("[Name] accepts connection [Conx].")	
		
		-- Set the protocol and the handling cell 
		ConxMgr <- Set.Protocol( Conx, "CLSPK", self )
	end 	
	
	-- The protocol has been set successfuly
	on CLSPK.Ready( cell Caller ) do
		keep Caller
	end
	
	-- The following are messages that the caller can send and that we respond to
	on HelloThere(ansi RemoteName) do
		system <- println("[Name]: [RemoteName] says hello to me")
		sender <- MyNameIs(Name)
	end
		
	-- The caller will send a series of test messages ..
	int ReceiveCount = 0	
	on TestMessage(byte[] Content) do
		ReceiveCount += 1
	end
	
	-- ..and ask how many were received
	on HowManyReceived do 
		-- answer
		sender <- Received(ReceiveCount, Name)
		
		-- we stop the test (pending messages will be sent)
		ConxMgr <- TCPIP.Close(Caller)
	end
	
end