JACK provides a runtime networking environment on which different agent processes can operate. Agents can address messages (MessageEvents, and BDIMessageEvents) to one another by specifying the name of the destination agent and, if applicable, its portal and host. The JACK runtime network then takes care of routing this message to its desired destination.
Not all agents need to run in independent JACK processes. Often more than one agent will share the same process. When this is the case, the routing of messages between them is trivial. All that the source agent needs to know is the destination agent's name to send the message accordingly.
For agents to communicate with one another, the following requirements must be met:
When agents are running in separate processes, The JACK communications layer needs to be used to allow these agents to communicate. This communications layer is known as the DCI network.
The DCI network is layered in such a way that different underlying transport mechanisms can be accommodated. By default, JACK uses the UDP transport protocol which is available on existing TCP/IP networks. This protocol is fast but connectionless and it does not guarantee delivery, so JACK provides a thin layer over UDP which provides reliable peer-to-peer communications.
Note: No call to any networking code is made unless a connection is actually requested or made possible (by specifying an explicit port number for the local portal). This means that machines with no networking installed will still be able to use JACK locally.
When agents in remote processes need to be able to communicate, the processes need to be told how to communicate with one another. Each process has its own portal and these connect to each other to provide a communications link for the agents in each process. A pair of portals can be connected explicitly, or a name-server can be used so that portals can connect on the fly as needed.
The full name of an agent takes the form agent@portal, where agent refers to the name given to an agent on creation and portal refers to the named portal assigned to the process in which the agent is running. The process may be running on a remote host or the local machine. To avoid ambiguity, it is recommended that the full name of an agent be used at all times when sending messages.
The easiest way to set up a DCI network is to designate one of the processes as a name-server. This simply means that whenever an agent tries to send a message to an agent at an unknown portal, the agent will query the name-server to try to locate the portal. If the name-server knows about the unknown portal, a connection to it is silently established. Otherwise, the message will be undeliverable and the send request will fail.
If there is no designated name-server, all connections must be explicitly requested. Any explicit connection request must be made by one (and only one) of the two processes comprising each connection.
Processes automatically keep their name-server(s) informed of new connections that they make. When a process makes an initial connection to a name-server, the name-server will update its list of known addresses. This can be used to implement a robust network containing two or more name-servers so that no information is lost if one name-server goes down and subsequently comes up again.
If a process exits for any reason, it can be restarted and communication will resume from the restart time. Any messages sent while the process was not running will be lost.
Portals, name-servers and connections can be established on the command line, provided that a call has been made to the JACK initialisation method:
aos.jack.Kernel.init(String[] args)
The simplest example is connecting two processes so that agents in each of them can communicate with each other. Suppose one of them is called Speaker and the other is called Listener. To connect them using a name-server, the two processes would be run as follows:
java Listener "-dci.new:listener=xxxx"
java Speaker "-dci.new:speaker" "-dci.ns:xxxx"
The first process creates a portal called listener bound to UDP port xxxx.
The second process creates a portal called speaker. It did not specify a particular port so a random port will be allocated for it. It also specifies a name-server, so it will connect to the name-server portal immediately.
Note: If the processes were running on different machines, the UDP port could have been specified as host:xxxx instead of just xxxx. Whenever the host is omitted in this way, the local host is assumed.
To connect the two processes using an explicit connection, the two processes would be run as follows:
java Listener "-dci.new:listener=xxxx"
java Speaker "-dci.new:speaker" "-dci.con:speaker->listener=xxxx"
As in the name-server example, the listener portal did not bother to choose a specific UDP port because there was no need. However, the listener portal had to specify a particular port so that speaker would know where to connect to.
Note: When connecting explicitly in this way, only one of the processes initiates the connection. Once connected, the communications path is bidirectional and completely symmetrical. Any unsuccessful connection attempts will timeout in 30 seconds by default.
An application can create a portal without the use of the -dci.new command line option. By default the portal associated with an application has name %portal, host localhost, and a port number that is the next available port. However, if the Java properties jack.portal.name, jack.portal.host or jack.portal.port are set, then these values will be used instead. This means that if the portal is being created solely for tracing purposes, (refer to the Tracing and Logging Manual), then there is no need to include an init(args) call in the main() method of the application.
Argument |
Purpose |
-dci.new:A=host:port |
Creates a new portal called A for this process. The host and port are optional. |
-dci.ns:host:port |
The given location ( host and port) is designated as a name-server. The host part is optional. |
-dci.con:A->B=host:port |
The local portal named A requests a connection to the portal named B which can be found at the given location ( host and port). The host part is optional. |
-dci.timeout=seconds |
This changes the default connection timeout from 15 seconds to the specified value. Use a timeout of 0 to wait indefinitely. |
Table 6-1: DCI command line summary
The above DCI command line functionality can also be achieved in the JACK code through the following static methods in the class aos.jack.jak.core.Dci.
The create method corresponds to the -dci.new command line argument. This method needs to be called before the first agent is created. name is the name of the portal, and desc is the description string that follows the '=' sign on a command line.
The connect method corresponds to the -dci.con:P1->P2=host:port command line argument. This method can be called at any time to establish a connection. lname is the local portal's name, rname is the remote portal's name, and rdesc is the description string that follows the '=' sign on the command line.
The nameserver method corresponds to the -dci.ns:host:port command line argument. This method can be called at any time to establish a new, additional name server to use. rdesc is the name server specification string that follows the "-dci.ns:" on the command line.
The setTimeout method corresponds to the -dci.timeout command line argument. This method can be called at any time to change the timeout period for the next connection request.
Note that all of the above methods except setTimeout() throw a DciException.
In addition, the following static methods are available to determine whether a particular agent is running and accessible on the DCI network.
This form of the ping method performs one ping only and does not attempt any connection. It does not distinguish between different types of failure and simply returns 'true' on success and 'false' on any kind of failure.
This form of the ping method performs one ping only and does not attempt any connection. This method times-out after 30 seconds. The possible return values are described in the table at the end of this section.
With this version of multiPingOk, if the given portal is not connected but a nameserver is present, then a connection attempt is made before the ping is attempted. One ping is attempted and if it is unsuccessful, more pings are attempted at intervals of 1 second for a total waiting period of 30 seconds. It returns 'true' or 'false' for success or failure.
This version of multiPingOk is like multiPingOk(String) but it allows the timeout and interval to be specified.
This version of multiPingOk is like multiPingOk(String) but it allows the timeout and interval to be specified plus it returns the same values as ping(String) which are described in the table at the end of this section.
The possible return values from the methods returning int are described in the following table:
Return value |
Meaning |
Dci.PING_NOT_READY |
There is no portal present in the current process. |
Dci.PING_UNKNOWN_PORTAL |
The given portal is not connected. |
Dci.PING_UNKNOWN_NAME |
The given name is not known at the given portal. |
Dci.PING_OK |
The given name at the given portal responded. |
Table 6-2: Return values from ping and multiPing
These values are defined in aos.dci.Portal.