(If you do not see the frame version
this page with a table of contents in the left frame, click here.)
The farVIEW Communications Library
The multi-threaded Comm library included in the farVIEW engine provides
a flexible TCP/IP interface for a farSlang module. You can use the
to access web pages on the internet. You can also use it to implement a
web server, a Remote-Procedure-Call (RPC) server, or any other kind of
server you want. The Comm library supports messages using the HTTP
I'll provide a short description of that later in this document, and
links to the primary document site. The thread management aspects of
library are transparent to the farSlang module.
The Comm Library
The library contains four main classes:
A user interface class, called CComm, which provides
between the user code and the communication threads.
A session handler class derived from the CThread class, called CSession,
which communicates with a remote correspondent, whether as a server or
as a client. The CSession class is designed to allow to be overridden
a derived class to provide specific server-side and client-side
A socket listener class derived from the CThread class, called CListen,
which listens for client messages and spawns server-side CSession
A socket handler class, providing a “low-level” interface to the
software, called CSocket.
Of these classes, you use only four functions in the CComm interface
to control the whole library.
There are several support classes, mostly acting as wrappers to
the communication between the farSlang module thread and the session
One special support class is CCommResult. Objects of this class
are passed by the farSlang module with a communication request, and are
used by the CSession thread to synchronize and communicate results back
to the farSlang caller. I will discuss this further later in this
The other support classes are not used by farSlang.
The Comm Interface
You do not interact directly with CSession, CListen, or CSocket.
you use the CComm class. The CComm class provides six simple interface
functions to control the Comm library:
OpenComm – engage the communication package. If a
create a CListen thread object and start the thread. (This function is
used only by farVIEW.)
CloseComm – disengage the communication package.
sessions and the disconnect the listener from WinSock. (This function
used only by farVIEW.)
OpenSession – create a CSession thread object
the specified identifier, URL, and port.
CloseSession – disconnect the specified CSession thread
SendMessage – send the specified message via the
thread object. If the message is to be encrypted (and authenticated),
is done automatically and transparently by the CSession thread before
message is sent.
ReceiveMessage – receive a message, authenticate and
If there is no message available, wait for it. Return the plaintext
to the farSlang module.
To properly control the Comm package, you open a session, send and
messages as needed, then you close the session. When you open a
you associate a unique identifier with that session. (Use the uniqueID
library function to obtain a unique identifier.) Use the session
in all subsequent commands to that CSession object to identify it to
Since this command should never be used by a farSlang module, I will
The basic actions taken when you call a CComm function are as follows:
Your code creates a CCommResult object, specifying synchronous or
behavior, and passes it, along with specific request parameters to the
appropriate CComm function.
The CComm function wraps the request parameters within a
and enqueues that object into the specified CSession object’s activity
request port. The CComm function then waits on the CCommResult
When it regains control, it will return to your code. If you secified
behavior, the wait step will not wait.
The specified CSession object dequeues the request from its
port, processes the request, then releases the CCommResult
If you specify synchronous behavior, the CComm function will wait until
the requested action is completed before returning control to you. This
is recommended. If you specify asynchronous behavior, the CComm
will return control to you immediately, where it becomes your
to determine when the action has completed. This is not recommended
you are tying up the machine while you are in the test loop. When
create a CCommResult object, the default is for synchronous behavior.
Let's examine a simple example. For this example, we will request a
web page from www.wdj.com (Windows Developers Journal). That is
the simplest thing to do. The result will be an HTML document that
links to obtain the images. We won't resolve the links, since we would
have to discuss HTML parsing, which is well beyond the scope of this
We will connect to www.wdj.com on port 80, which is the normal HTTP
port, send a GET request to the server, receive the server's response,
and disconnect from the server.
Connecting to a Host
Obtain a unique identifier, then open the session. Retain the sessionID
for subsequent calls.
-- The CComm object is in the System global glb System: CSystem
-- Get a session identifier var sessionID := UniqueID
-- Create a CCommResult object var result := CCommResult -- defaults to wait
-- Open a session System.Comm.OpenSession(sessionID,
"http://www.wdj.com", 80, "", result)
Note that error checking is omitted from the examples for clarity.
normal coding, you should include error checking, and we will discuss
later in this document.
Sending a Message to a Host
Use the sessionID created above along with the content of the message
to send in this call.
-- Send a request to an HTTP server var body: CAtom -- no body for a "GET" System.Comm.SendMessage(sessionID,
The SendMessage command has the most parameters.
Receiving a Message from a Host
Continue to use the same sessionID to request to receive a message
-- Receive the server's response System.Comm.ReceiveMessage(sessionID, result)
-- The content of the server's response -- is in the result object.
-- Obtain the header list and -- write it to a file result.GetHead.WriteFile("head.txt")
-- Obtain the body (content) and -- write it to a file result.GetBody:CStrList.WriteFile("body.txt")
Disconnecting from a Host
Disconnect the session from the host
from the server System.Comm.CloseSession(sessionID, result)
Acknowledging a Guest
Of course, there is more to acknowledging the guest's request than just
the ACK-message, but let's just send the text of the guest's message
to her for now.
-- Send the body-part of the guest's -- message back to the guest. glb System: CSystem System.Comm.SendMessage(System.SessionID,
When implementing a connection between two farVIEW computers, you need
to know either the URL of the host machine or its IP address. You can
find its IP address by opening a Windows Command Window (MSDOS), and
at the prompt. You will see something like the following.
192.x.x.x is a local IP address, which is what you should use if you
are working on a LAN. If you are setting up for Internet access,
that one won't work. In my case, the Internet IP address is
However, because, my ISP assigns a new IP address to my machine
I log on, that one won't work generally either. In fact, unless you
a DSL or Cable connection, you may not have a permanent IP address
for your machine. That pretty much eliminates that machine as a farVIEW
host, unfortunately, except for just the immediate session.
Building an HTTP Server
About the HTTP Protocol
Implementing Remote Procedure Calls
The farVIEW engine can be used as a portal for implementing remote
calls fairly easily. For this discussion, I will show how to write a
farSlang server and a farSlang client to do something trivial.
Let's ask a server to double a value provided by a client. The
for its part, will show a dialog to obtain the value, send the value to
the server, then display the result when it is returned.
-- Sample RPC server module in farSlang to double the
the body -- of the message and return it. -- -- Note that the server code must reside within a proc, in
case, -- proc double. Also note that the SendMessage and
CloseSession -- commands used in this code are not immediately carried out
are -- enqueued into the inPort of the same thread in which this
module -- executes, and cannot execute until this module completes.
Therefore, -- the module code must not attempt to wait until the
are -- completed, since if it does, they will never even be
module RPCServer glb System: CSystem var result :=
-- don't wait for completion
proc double -- Get the value, double it,
replace the old value
System.CommBody:CStrList.GotoHead var val# :=
* val, 10))
-- Return the result to the
and shut down
System.Comm.CloseSession(System.SessionID, result) endProc double
For the purposes of this discussion, you can test on a single machine
using the standard 127.0.0.1 IP address. That way, your farVIEW will
as both the client and the server.
-- Sample RPC client module in farSlang to get a value
user, -- send it to the sample server to double the value then
the -- value to the user.
-- Receive the result
-- Shut the session down
-- Extract the result and
it body := result.GetBody:CStrList body.GotoHead return body.StrItem(true) endProc getValueFromServer
-- Display a Accept dialog to get a number var accept := CAcceptDialog(nil) accept.SetEntry("Enter Number:", "", "A", 64) accept.Accept("RPC Sample Client") var value := accept.GetAcceptValue("Enter", true)
-- Send it to the server and get the result value := getValueFromServer("127.0.0.1",
-- Display the result to the user CMessageBox("The host said...", value).Run endModule RPCClient
The sample code does not check for errors.
Note that the server parameter value in the SendMessage
in the client identifies the farSlang module (RPCServer.double) to
as the server.
You can easily execute a Windows program remotely. For example, to
Word remotely, add the following lines to the server module.
var launch := CLaunch launch.LaunchChild("Word") repeat until launch.IsChildDone
You will find this code in RPCLaunch.far.
The modules shown in this document are in the farSlang library in
release. Look for RPC*.far.