#
# @(#)server.mac 5.2 01/10/02 CSS
#
# "Spec" Release 5
#
# Copyright (c) 2002
# by Certified Scientific Software.
# All rights reserved.
# Copyrighted as an unpublished work.
#
#########################################################################
#
# Spec "server" macros
#
# Macros for simple communication between two instances of spec,
# with one instance acting as a remote server, the other as
# a client sending commands.
#
# The server and the client need to use the same port number.
#
# For example, on the server system (named TheServer) execute the command:
#
# server 6666
#
# From the other system first execute the following to connect to the
# host with the name TheServer:
#
# remote_setup TheServer 6666
#
# Then you can run commands from on TheServer with:
#
# r wa
# r umvr tth 1
#
# To receive a reply from the server, send the command using the
# remote_send() function directly, as in
#
# print remote_send("2 * PI")
# S[det] = remote_send("S[det")
#
# Note, there is presently no way to abort a command running on the
# server from the remote client.
#
# Note, also, turning on simulate mode on the server from the client
# will stop the server from responding to commands, so don't do that.
#
# Only one client at a time can connect to the server. However, it
# is possible for multiple clients to access the server in a round-
# robin fashion.
#
# If the global variable SERVER_SHARE is zero (the most efficient
# for a single client), the connection will be maintained over multiple
# commands to the server, locking out other clients. If SERVER_SHARE
# is nonzero, each client will disconnect from the server after sending
# a command, allowing another client to connect.
# Start the server at the specified port number
def server '{
global SERVER_PORT
if ($#) {
SERVER_PORT = $1
} else if (SERVER_PORT == 0) {
eprint "Usage: server port_number"
exit
}
if (set_sim(-1)) {
eprint "Can\'t run server in simulate mode."
exit
}
server_func()
}'
# close twice to remove the listen socket and the connection socket
def server_cleanup '{
local s
cdef("cleanup_once", "", "_server_clean_", "delete")
s = "localhost:" SERVER_PORT
sock_par(s, "close")
sock_par(s, "close")
}'
def server_func() '{
local s cmd ret
cdef("cleanup_once", "server_cleanup\n", "_server_clean_")
s = "localhost:" SERVER_PORT
sock_par(s, "listen")
sock_par(s, "timeout", 0)
print "Entering server loop. Type ^C to quit."
while (1) {
cmd = sock_get(s, 0)
if (cmd == 0 || cmd == "")
continue
printf("** %s", cmd)
ret = eval(cmd)
printf("== %s\n", ret)
sock_put(s, sprintf("%s\n", ret))
}
}'
# Enter server host and port info
def remote_setup '{
global SERVER_ID, SERVER_SHARE
if ($# != 2) {
eprint "Usage: remote_setup hostname port_number"
exit
} else
SERVER_ID = "$1" ":" "$2"
}'
def r \'remote\'
def remote '{
remote_send("$*")
}'
# close the connection to the server, allowing other clients to connect
def remote_cleanup() '{
cdef("cleanup_once", "", "_remote_clean_", "delete")
sock_par(SERVER_ID, "close")
}'
# sent the command and receive the reply
def remote_send(cmd) '{
local r
if (!SERVER_ID) {
eprint "Call \"remote_setup\" first."
exit
}
if (!sock_par(SERVER_ID, "connect")) {
eprintf("\
Can\'t connect to \"%s\".\n\
Have you started \"server\" on the remote system?\n", SERVER_ID)
exit
}
cdef("cleanup_once", "remote_cleanup()\n", "_remote_clean_")
sock_par(SERVER_ID, "timeout", 0)
sock_put(SERVER_ID, sprintf("%s\n", cmd))
ote_clean_", "delete")
sock_par(SERVER_ID, "close")
}'
# sent the command and receive the reply
def remote_send(cmd) '{
local r
if (!SERVER_ID) {
eprint "Call \"remote_setup\" first."
exit
}
if (!sock_par(SERVER_ID, "connect")) {
eprintf("\
Can\'t connect to \"%s\".\n\
Have you started \"server\" on the remote system?\n", SERVER_ID)
exit
}
cdef("cleanup_once", "remote_cleanup()\n", "_remote_clean_")
sock_par(SERVER_ID, "timeout", 0)
sock_put(SERVER_ID, sprintf("%s\n", cmd))
r = sock_get(SERVER_ID, 0)
if (SERVER_SHARE)
remote_cleanup()
return(r)
}'
|