TcpIp using the same port
In the previous example we had one cell connecting to another remote cell using an ip address and a port number.
In this example we show how the same address and port number can be used to set up many communications to the remote system.
Note that when the communication with a remote system is set up, you simply use the cell references you get from the remote system to send messages to cells, in just the same way as you do for a local system.
You do not need to set up a communication for each cell you want to communicate with.
You can for example ask the remote system the cell reference for this or that service and then simply use the cell reference to send messages to.
But before you can have any idea which system you are talking to, you have to set up the connection.
In later examples we will see that a connection can be used also for different protocols
then the CellSpeak protocol which is used to cummunicate between systems running a CellSpeak VM.
When a CellSpeak connection is established between two systems,
a special cell is created automatically at each side of the communication: the avatar.
Whenever you send a message to a cell on the remote system, it actually goes to the message queue of the avatar.
The avatar will then do the actual sending of the message using the protocol that was agreed between the two systems.
The fact that there is an avatar is fully transparent to the application.
Messages that are received over a connection do not transit via the avatar, but are delivered directly to the message queue of the destination cells.
Apart from the avatar, which packages and sends messages, you also might want to have a cell that handles the comms channel
for example to initiate some special action when the communication is lost. For this purpose you can specify your own 'handler' cell.
(1) In this case we do all the connections at the same place - in reality an application could very well connect to a remote system in several places.
(2) The Conx parameter is a reference to the connection used for the comms between the two systems.
We need it here to set the protocol for the communication between the two systems - we do not need to store it.
(3) A connection determined by an ip-address and port number, can only handle one protocol.
If the protocol would already have been set to a different type, then the Humanoid would get an error message.
(4) The avatar stands for the cell that is listening on the other side of the connection.
(5) When a reply comes back, it will not come from the avatar, but from the cell on the other system.
12 TcpIp using the same port.celsrc
use Windows, Math, Strings, Editor, System
design ConxTest is
cell Caller, Callee
cell Creator
cell stdout
constructor is
stdout = create MenuWindow("Connecting to a remote CellSpeak system over Tcp/Ip")
system <- stdout.Set(stdout)
create TalkerDesign("Apollo","27524")
create ListenerDesign("27524")
end
end
design TalkerDesign( ansi Remote, ansi Port) is
cell ConxMgr
keep Remote, Port
constructor is
system <- Service.Get("ConxMgr")
end
on Service.Provider(ansi Service, cell Provider) do
Service is "ConxMgr" ? ConxMgr = Provider : yield
(1) for i=1 to 5 => ConxMgr <- TCPIP.Connect(Remote, Port)
end
var Count = 0
(2) on TCPIP.Connected( ConxClass Conx ) do
cell Humanoid = create HumanoidDesign("Humanoid[Count+=1]")
(3) ConxMgr <- Set.Protocol( Conx, "CLSPK", Humanoid )
system <- println("\tconnection to [Remote] port [Port] established.")
end
end
design HumanoidDesign(ansi Name) is
keep Name
cell Avatar, ConxMgr
(4) on CLSPK.Ready( cell Avatar ) do
keep Avatar
ConxMgr = sender
system <- println("[Name]: contacting other system")
(5) Avatar <- HelloThere(Name)
end
on TCPIP.RemoteDisconnected( ConxClass Conx) do
system <- println("[Name] Remote Disconnected")
end
on MyNameIs(ansi NameCallee) do
system <- println("[Name]: my counterpart's name is [NameCallee]")
for i=1 to 5000 => sender <- TestMessage("Message [i]:0123456789 abcdefghijklmnopqrstuvwxyz")
sender <- HowManyReceived
end
on Received(int count, ansi CalleeName) do
system <- println("[Name]: [CalleeName] received a total of [count] messages")
sender <- DemoIsOver
destroy self
end
destructor is
system <- println("[Name] going down")
ConxMgr <- TCPIP.Close( Avatar )
end
end
design ListenerDesign(ansi Port) is
cell ConxMgr
keep Port
constructor is
system <- Service.Get("ConxMgr")
end
destructor is
ConxMgr <- TCPIP.Stop.Listening(Port)
end
on Service.Provider(ansi Service, cell Provider) do
Service is "ConxMgr" ? ConxMgr = Provider : yield
ConxMgr <- TCPIP.Listen( Port )
end
int Count = 0
on TCPIP.Accept( ConxClass Conx ) do
system <- println("\taccepting connection [Conx].")
var NewRobot = create RobotDesign("Robot[Count+=1]")
ConxMgr <- Set.Protocol( Conx, "CLSPK", NewRobot)
end
end
design RobotDesign(ansi Name) is
keep Name
cell Avatar, ConxMgr
on CLSPK.Ready(cell Avatar) do
keep Avatar
ConxMgr = sender
system <- println("\tReceived avatar")
end
on TCPIP.RemoteDisconnected( ConxClass Conx) do
system <- println("[Name] Remote has closed the connection")
end
on CLSPK.NotSupported do
system <- println("CLSPK is not supported")
end
on HelloThere(ansi RemoteName) do
system <- println("[Name]: [RemoteName] says hello to me")
sender <- MyNameIs(Name)
end
int ReceiveCount = 0
on TestMessage(byte[] Content) do
ReceiveCount += 1
end
on HowManyReceived do
sender <- Received(ReceiveCount, Name)
end
on DemoIsOver do
destroy self
end
destructor is
system <- println("\t[Name] going down")
ConxMgr <- TCPIP.Close( Avatar )
end
end