Using SM32 in Multi User and Enterprise Environment
Overview
In general there are 2 configuartion types of Multi User SM32, they are FAT and THIN Clients.
Both use the same SM32.EXE on the desktop. In general the only files that are distributed to
the client desktop (both FAT and THIN) are SM32.EXE and SM32.SM32 config file. To
better understand multi user configurations consider the following single user
SM32 diagram:
Fat Client
Under SM32 the term FAT client means that most if not all SM32 programs
are executed by the
desktop computer. Programs and data are normally accessed via a Remote
File Server in stead of the
Local File Server. This is accomplished by using a
ROUTE.
The default route (no route # in the pathname) is the Local File Server. Other routes can be established
using the ROUTE command but normally routes are established in
the configuration and then never changed. The route number is then used in the
SETDISK command or in the configuration setdisks.
The following is a sample of setting differences between a single
user environment an a multi user environment running the same set of programs.
The sample uses a Remote File Server running on a
Linux Server serving port # 5000.
Property PAGE
-SETTING |
Single User | Multi User | Functionality |
|---|
System-
# of Programs in Disk Cache |
0 | 100 |
Establishes program disk caching in C:\SM32CACHE on the client PC. The 100 most recently used programs
will be cached. When a program is accessed from the cache and it's header has not been verified in
the last 2 hours (7200 seconds), the program header is retrieved from the File
Server. If the retrieved program header indicates the program
has been modified it is reloaded. Only one instance SM32 can be using any single cache
directory at any single time.
|
System-
Expire Seconds |
0 | 7200 |
System-
Cache Directory |
  | C:\SM32CACHE |
Network-
ROUTE: |
  | 0,2,"192.168.1.3:5000" |
Establish Route # 0 to Remote File Server |
Disk I/O-
SETDISK: |
0,"PROGS" 1,"DATA" 9,"UTIL" |
0,"<0>/u/net/PROGS" 1,"<0>/u/net/DATA" 9,"<0>/u/net/UTIL" |
do the SETDISK's |
Temporary files are normally located on the PC using the Local File Server.
File Server
The File Server is distributed as SM32FS.EXE for windows and sm32fs for linux.
Windows
Windows supports 2 connection types:
Type 1 - Named Pipes
Type 2 - TCP/IP Sockets
SM32FS.EXE is installed from a console mode prompt as follows:
sm32fs -install max_connections connection_type type_param {root_directory}
The install installs and starts a windows service.
Examples:
sm32fs -install 64 2 5010 C:\SM32FS
Maximum clients is 64
Socket type connection serving port 5010
No file access outside of C:\SM32FS and its subdirectories
ROUTE command to connect:
ROUTE 0,2,"192.168.1.3:5010"
if server IP is 192.168.1.3
sm32fs -install 50 1 \\.\pipe\SM32FS C:\SM32FS
Maximum clients is 50
Named Pipe type connection Pipe Name SM32FS
No file access outside of C:\SM32FS and its subdirectories
ROUTE command to connect:
ROUTE 0,1,"\\MYSERVER\pipe\SM32FS"
if server name is MYSERVER
The service can be uninstalled with:
sm32fs -remove
Linux
Linux only supports the Socket type connection:
The following line could be added to /etc/rc.d to start sm32fs at boot time.
(cd /u ; /usr/bin/sm32fs 50 2 5000 /u)
Maximum clients is 50
Socket type connection serving port 5000
No file access outside of /u and its subdirectories
Thin Client
#!/bin/sh
(cd /u ; su -c "/usr/bin/sm32fs 50 2 5000 /u" chris)
(cd /u ;/usr/bin/sm32server 5001)
SM32 Pipes
SM32 Pipes allow multiple SM32 user programs (clients) to
communicate with an SM32 server program. The pipes use standard SM32 I/O. They are
not intended to be used to communicate with non-sm32 programs
(SEE SOCKET for this purpose). SM32 Pipes are implimented
using TCP/IP sockets but are less complex for the SM32 programmer to impliment.
There are 2 things to define to get started:
1. A port number usually 5000->9999 are available
2. Choose a location to define the "PIPE" file that the server and all clients have
access to. This would mean a directory share or a ROUTE.
PIPE "MYPIPE",6000,4
Where SETDISK #4 is something like:
SETDISK 4,"\\MYSERVER\PUB\SHDISK"
or
SETDISK 4,"<0>SHDISK"
Both the Server and the Clients must be able to OPEN "MYPIPE"
One thing should be made clear, "MYPIPE" is a disk file but it has
nothing to with the PIPE I/O. It is only used to store the port #
and the SERVERS IP address.
The SERVER opens the pipe:
100 OPEN(1,SERVER=#TRUE)"MYPIPE"
For the SERVER open SM32 checks that there is not already a SERVER
and if not places the IP address of this user in the "MYPIPE" file.
SM32 then starts SERVING the port and sets up to ACCEPT connections
on the PORT.
A CLIENT opens the pipe:
100 OPEN(1)"MYPIPE"
For the CLIENT open SM32 checks the "MYPIPE" file to get the port #
and the SERVER's IP address. If there is a SERVER SM32 CONNECT's to
the SERVER if not the CONNECTion will be attempted at the 1st WRITE.
Consider the following 2 programs. (These are working programs you
can cut and paste (use edit all) into SM32. You will need to do
the PIPE define to test them.)
SERVER Program
0010 BEGIN
0020 OPEN (1,SERVER=#true)"MYPIPE"
0030 READ (1)A,A$
0040 LET R=IND(1);REM "return response to connection R"
0050 IF A>=0 AND A<=2 THEN GOTO 0090
0060 LET A$="Invalid Request"
0070 WRITE (1,IND=R)A$
0080 GOTO 0030
0090 ON A GOSUB 1000,2000,3000
0100 WRITE (1,IND=R)A$
0110 GOTO 0030
1000 REM 1000 REQUEST # 0
1010 PRINT "request 0 - ",A$
1020 LET A$="Result of Request # 0"
1030 RETURN
2000 REM 2000 REQUEST # 1
2010 PRINT "request 1 - ",A$
2020 LET A$="Result of Request # 1"
2030 RETURN
3000 REM 3000 REQUEST # 2
3010 PRINT "request 2 - ",A$
3020 LET A$="Result of Request # 2"
3030 RETURN
Client Program
0010 BEGIN
0020 OPEN (1)"MYPIPE"
0030 INPUT "Enter Request (0->2):",A
0040 INPUT "Extra Request Data:",A$
0050 WRITE (1)A,A$
0060 READ (1)A$
0070 PRINT A$,'lf'
0080 GOTO 0030
This is an example of a trivial transaction server. It has no state
information about the connection. It takes a request, handles it and
returns a result.
The SM32 PIPE should have been called a FUNNEL as it contains multiple connections
on one end and a single connection on the other. The first implimentation of the SM32 Pipe
had no syntax for the SERVER to respond to CLIENT( the use of IND). In that version the
SERVER was called the READER and the CLIENTs were called the WRITERs.
SM32 Sockets (TCP)
SM32 Sockets allow an SM32 program to act as a CLIENT or SERVER and communicate with any
computer that supports TCP/IP sockets. The program on the other end of a connection may or
may not be an SM32 program.
The WAITIO was added to SM32 to allow an SM32 server program to PEND
waiting for connections and/or incoming data on multiple connections.
The following 2 programs are logically equivalent to the SM32 pipe example.
SERVER Program
0010 BEGIN
0100 REM 100,5
0105 LET M=2;REM max connections -1
0110 DIM C[M];REM max M+1 connections
0115 FOR I=0 TO M;LET C[I]=0;NEXT I
0120 KEEP_SERVING:
0125 GOSUB GET_SCHAN
0130 IF S<>0 THEN GOTO 0145
0135 SOCKET (99,SERVER=#true)"6000";CLOSE (99);REM already M+1 connections
0140 GOTO KEEP_WAITING
0145 SOCKET (S,SERVER=#true)"6000"
0150 KEEP_WAITING:
0155 WAITIO 3000
0160 FOR I=0 TO M
0165 IF C[I]=0 THEN GOTO 0255
0170 READ RECORD(C[I],SIZ=2,TIM=0,ERR=.+1)L$;GOTO 0195
0175 IF ERR=0 THEN GOTO 0255
0180 CLOSE (C[I]);LET C[I]=0
0185 IF S=0 THEN LET S=-1
0190 GOTO 0255
0195 LET L=DEC(L$)
0200 READ RECORD(C[I],SIZ=L)A$
0205 LET A=NUM(A$(1,1)),A$=A$(2)
0210 IF A>=0 AND A<=2 THEN GOTO 0235
0215 LET A$="Invalid Request"
0220 LET A$=BIN(LEN(A$),2)+A$
0225 WRITE RECORD(C[I])A$
0230 EXITTO 0160
0235 ON A GOSUB 1000,2000,3000
0240 LET A$=BIN(LEN(A$),2)+A$
0245 WRITE RECORD(C[I])A$
0250 EXITTO 0160
0255 NEXT I
0260 IF S=-1 THEN GOTO KEEP_SERVING
0265 IF S=0 THEN GOTO KEEP_WAITING
0270 LET C$=FID(S,ERR=.+1);GOTO 0280
0275 GOTO KEEP_WAITING
0280 FOR I=0 TO M
0285 IF C[I]<>0 THEN GOTO 0300
0290 LET C[I]=S;REM we are connectted
0295 EXITTO KEEP_SERVING
0300 NEXT I
0305 ESCAPE ;REM can' be here
1000 REM 1000 REQUEST # 0
1010 PRINT "request 0 - ",A$
1020 LET A$="Result of Request # 0"
1030 RETURN
2000 REM 2000 REQUEST # 1
2010 PRINT "request 1 - ",A$
2020 LET A$="Result of Request # 1"
2030 RETURN
3000 REM 3000 REQUEST # 2
3010 PRINT "request 2 - ",A$
3020 LET A$="Result of Request # 2"
3030 RETURN
8000 REM 8000,5
8005 GET_SCHAN:
8010 FOR I=0 TO M
8015 IF C[I]=0 THEN EXITTO 8035
8020 NEXT I
8025 LET S=0
8030 RETURN
8035 LET S=UNT
8040 RETURN
Client Program
0010 BEGIN
0020 SOCKET (1)"192.168.1.100:6000"
0030 INPUT "Enter Request (0->2):",A
0040 INPUT "Extra Request Data:",A$
0050 LET B$=STR(A)
0060 LET A$=B$(1,1)+A$
0070 LET A$=BIN(LEN(A$),2)+A$
0080 WRITE RECORD(1)A$
0090 READ RECORD(1,SIZ=2)L$
0100 LET L=DEC(L$)
0110 READ RECORD(1,SIZ=L)A$
0120 PRINT A$,'lf'
0130 GOTO 0030
As can be seen by the number of lines of code the server program is quite a bit more
complex than the PIPE example while client program is very similar.
The complexity arises from the server having to have a unit # for each connection.
The server starts by having a 'SERVing' unit # that
waits for a connections (S in the example).
Once a connection is made the unit # is transformed into a 'CONNECTed' unit # (S is placed in the C[] - line 0290).
The program detects that the 'SERVing' unit # has become a 'CONNECTed' unit # by using the FID function.
The FID functions gives an error on a 'SERVing' unit # and returns the peers IP and PORT of a
'CONNECTed' unit # (line 0270). Because of this transformation of unit # type SM32
internally serves a port # once an initial serve has been made. This avoids missing a connection. Once
maximum # of connections has been reached (M+1 in the example) the internal serving can be stopped by
serving and then closing the serving unit #(line 0135). A WIATIO (line 0155) is used to wait for incoming data and
connections. NOTE: ALL data MUST be read and any connection must be handled before returning to the WAITIO.
SM32 Sockets (UDP)
SM32 UDP Sockets allow an SM32 program to act as a CLIENT or SERVER and communicate with any
computer that supports UDP sockets. UDP Sockets are a connectionless,
unreliable datagram (record) protocol. In contrast TCP Sockets are a connection-oriented
reliable byte stream.
Creatation:
0100 SOCKET(1,UDP=#true)"5555";REM serve udp port 5555
0200 SOCKET(2,UDP=#true)"";REM get a UDP socket
Reading:
0110 READRECORD(1)A$
Writing:
0210 WRITERECORD(2,IPA="192.168.1.1:5555")A$
0120 WRITERECORD(1)A$; REM send record to the last computer you received from.
Get Last Senders IP address:
0115 P$=IPA(1)
SEE:
CONNECT  
RCALL  
ROUTE  
PIPE
SOCKET
WAITIO