Sockets

From Jmol
Jump to navigation Jump to search

Why sockets?

Jmol supports socket communication between two independent instances that are running on one single or two different computers. Sockets enable one Jmol instance to send commands to the other for execution. It is also possible to send arbitrary data to be captured in a variable. The Molecular Playground project is a practical application of Jmol sockets. Jmol socket communication is conducted using the sync command, for which documentation can be found at Jmol docs – sync and in the Inter-Application Communication protocols. The latter document makes clear that the inter-app messages take the form of JSON-encoded messages such as {"type" : "command", "command" : "background white"}. Jmol manages this JSON wrapping for us in the nature of the sync command.

Basic commands

Communication between a pair of Jmol applications requires that one be started first with the option -j "sync -8008" (designated server) and a second (client) with -j "sync 8008". The port 8008 is used as an example; any valid, available port nnnn can be used. For Jmol-Jmol communication, it's as simple as that. The appropriate handshake has been exchanged and any subsequent command sent with sync 8008 "command" from either app will result in action at the other. For example, sync 8008 "background white" entered in the console of the server instance will produce the white background at the client instance (and vice-versa). For practical purposes, there's no further distinction between the client and server nodes; however, inspection of the traffic reported as stdout in the shell that started each node reveals that the server is sending much more traffic – related to mouse movements and keyboard activity. This is by design and can be exploited with set syncScript ON and set syncMouse ON.

Arbitrary data

In the following discussion, server refers to the Jmol instance sending a command with sync and client refers to the instance receiving and executing, irrespective of which was started with the -nnnn port. It is handy to define a Jmolscript function send to simplify command formatting.

function send (s) {sync 8008 s}
facilitates sending a command as in send ("load $CC") to have the client load an ethane model. It can be used to send arbitrary data such as
send ("d=[1,2,3];print d")
which will create the var d with the value [1,2,3] on the client and then display [1,2,3] on the client console. Note that the client receives the string and then executes the symbols contained therein. If one wants to retain string property, nested quotes are needed.
send ("d=' " + "c' ")
yields the command d='c' at the client.

It's yet more useful when the target Jmol also has a function send, so that it can easily send an arbitrary reply.

send ("function send (s) {sync 8008 s}") will define the same function at the client.

The command sequence

send ("load $CC") (1)
send ('c=write("coords")') (2)
send('send ("d=\' " + c + "\' ")') (3)

results in a model of ethane on the client (1) from which the xyz format coordinates are stored initially in var c on the client (2) and finally sent back to the server to be stored in var d on the server (3) as can be demonstrated subsequently by

print d; load '@d'
which will display at the server the ethane model created on the client.

Note that the single and double (and escaped \') quotes in (3) are a necessary pattern to produce a command that the client can execute as send (" 'd = ' c") where d = is string that the server treats as symbol and loads with the contents of c. There are other patterns that will accomplish the same result within the constraint that the JSON-encoded {"type" : "command", "command" : 'send ("d=\' " + c + "\' ")'} is how it travels over the socket.

Similar results can be achieved between Jmol and a python script. See Python for an example.

Contributors

GWhitwell