UCM Unitec Home Page
      

Chapter 5 - Active-X Introduction

5.1. Overview
5.2. UCM Messages
5.3. Addressing Methods

5.3.1. Message ID
5.3.2. TCP/IP Address
5.3.3. Communication Space
5.3.4. Global Communication Space
5.3.5. Terms

5.4. AutoStart Processes
5.5. Closing an UCM Connection
5.6. UCM Error Handling

5.1. Overview

This chapter contains an introduction to the features of the UCM Active-X control Ucm.ocx. To make full use of the control, it is important to understand the underlying concepts. Please read the following section carefully. All examples used in this chapter assume a VB program with a form named Form1 containing an UCM control named Ucm1.

5.2. UCM Messages

An UCM message consists of a message ID and the message body. The message ID serves as the lowest level addressing component in the data transport. Sending a message requires the OutputID(P) property to be set. To receive UCM messages a control must set the InputID(P) property to the message type it is ready to accept. Except when specifying the wildcard ID "*", which means 'any', only one message type can be received by a control at a given time.

Message ID Message Data


Input message data may optionally be subdivided into fields by setting the Delimiter(P) property. Fields can be accessed by the Field(M) method:

Message ID Field : Field :

Field

5.3. Addressing Methods

5.3.1. Message ID

UCM supports several addressing methods. As stated above, the message ID constitutes the lowest level in the addressing scheme. It controls data distribution of messages sent from the local or a remote system. The control in the following example will receive all local and remote messages with ID someID:

Sub Form1_Load()
    Ucm1.InputID = "someID"
End Sub

Sub Ucm1_DataInput()
    Debug.Print "Input event, got message:"; Ucm1.InputMsg
End Sub


If several controls are waiting for the same message ID, UCM will duplicate the message and broadcast to each of them. To perform a local data transfer, another program could be used:

Sub Form1_Load()
    Ucm1.OutputID = "someID"
    Ucm1.OutputMsg = "Hello World"
End Sub


Even a second Active-X control contained in the same program could be the sender of such a message. Of course, a control will never receive a message that has been sent by itself. If no Ucm.ocx is ready to receive a local message posted, an Error(E) event is raised in the sending control and the message is discarded (see the AutoStart feature below for an exception of this rule).

The special wildcard InputID "*" matches any message ID value.

5.3.2. TCP/IP Address

The next higher addressing level consists of the TCP/IP address of the server thread or process.

To establish a TCP/IP Client-Server connection, the client must know the IP address of the system providing the server functionality. In addition, each connection type is identified through a unique port number. The TCP/IP hosts and services control files define symbolic names for the standard IP addresses (hosts) and for most of the ports (services) used in a network environment. Using these symbolic  names requires the hosts and services file to be present on each network node, i.e. on the host and on all client systems. On Unix systems, the files are located in the /etc directory. On Windows systems the location varies depending on OS type and version. Each line in the hosts file contains the standard four number IP address and one or more symbolic alias names. Each line in the services file holds the service name, a port number and a port type (for UCM communication the type should always be tcp). To avoid conflicts with standard TCP/IP ports, these numbers should have values > 5000 assigned by convention. Unitec products use port numbers in the range from 6800 to 6999.

Important note:

In TCP/IP programming a communication link between a server and a client is established by the use of an entity called socket, introduced by UCB University of California at Berkley, also referred to as BSD sockets. A socket is defined by the IP address of the two participating systems and a so called port number. Port numbers often have a symbolic service name assigned in a control file named services, but internally the number is used as is. Many well known port numbers (reserved services) are defined in the range between 1 and 1023, but room should be left for extensions. By convention, user port numbers should have values > 5000 assigned. Unitec software uses port numbers in the rage 6800 to 6999, e.g. for a future version of the license manager the port 6800 has been reserved and the CSS spooler uses port 6801. To avoid conflicts with standard TCP/IP and Unitec ports, you should use numbers in the range 5001 to 6799 or >= 7000.


To initialize an UCM control for non local communication, the Host(P) and Port(P) properties must be set. Both values may be given in either symbolic or standard numeric notation. To reduce administration overhead, it is recommended to use the numeric addressing method. This removes the need to maintain similar copies of the hosts and services file across the network:

Sub Form1_Load()
    Ucm1.AdrMode = ucmTCP
    Ucm1.Host = "128.41.1.3"
    Ucm1.Port = "7201"
    Ucm1.InputID = "form1"
    Ucm1.OutputID = "form1"
    Ucm1.Delimiter = ":"
    Ucm1.OutputMsg = "Request address of customer 8712"
End Sub

Sub Ucm1_DataInput()
    Dim name as String
    Dim street as String
    Dim city as String

    ' Ucm1.InputMsg might contain:
    ' "Unitec:Im Lot 10:Uster"
    name = Ucm1.Field(1)
    street = Ucm1.Field(2)
    city = Ucm1.Field(3)
    ...
End Sub


The scope of possible input messages of the Ucm1 control in the above example is now reduced to the socket identified by the Host and Port properties and which is automatically established by the communication manager upon the first output operation. Even if a message with the same "form1" ID enters the system and has to be distributed, Ucm1 will only receive the message if it origins from the socket it is attached to. The deeper the addressing level is defined, the closer the data sink object can be determined. Now consider another form in the same program, with its own UCM control needing to communicate with the same server process. This second form Form2 would have to initialize its control exactly the same way, except that it should set its InputID and OuptutID to a different value, e.g. "form2". Failing to do so, would cause both forms to receive any response message, regardless of the sender of the request. In fact it is common practice for a program to have one UCM control per form, each addressing the same server process, but with distinct message IDs. The server program normally analyzes a request message and sends one or several response messages with the same message ID that was used in the request. The first form of the client program that sends a message by assignment to its OutputMsg(P) property causes UCM to establish a connection to the server by creating a socket. All other controls that refer to the same address are attached to the already existing connection.

There remains one problem: what if two invocations of the same program are running? Since they both use the same message IDs on say Form1, and the same TCP address, will not each program also get response messages to requests that origin from the other copy of the program? The answer is yes, they both share the same socket (i.e. communicate with the same copy of the server thread or process) and the broadcast feature of UCM will duplicate input messages for each control listening for the same message ID. This might be what we require, but normally it is exactly the behavior we do not want.

Before introducing the highest addressing level, the communication space, we have to take one more close look at the example above. The AdrMode(P) property is used as:

    Ucm1.AdrMode = ucmTCP

An alternative to the ucmTCP mode is ucmService. It uses the Service(P) property to specify the server address instead of the Host and Port properties. By using the UcmConf(U) utility, a symbolic service name can be defined for a host and port address pair. This UCM service name can then be assigned to the Service property. When installing software in many different environments, the advantages of symbolic names that can be configured externally over hard coded addresses are obvious.

Hint:

Use UcmConf(U) to properly configure one client system in a new network environment. Once you have verified correct operation, run the Windows regedit and navigate to the location

HKEY_LOCAL_MACHINE\SOFTWARE\Unitec\Ucm\Services

Choose the export option to write the selected branch to e.g. services.reg. Copy this file to the other client systems and double click on it from the Windows Explorer. This will import the same settings into the new clients registry.


UCM
controls have their TCP/IP address set if either AdrMode(P) is ucmTCP and Host(P) as well as Port(P) are not empty, or AdrMode(P) is ucmService and Service(P) is not empty. Such controls are said to be bound, all other controls are unbound.

5.3.3. Communication Space

Remember the problem of two or more concurrent invocations of the same program described above? In such a situation, we normally do not want to share the same socket connection between different processes. Starting with UCM Release 2.0 an additional addressing level, the so called communication space, has been introduced. It is identified by a long integer and can be set using the CommID(P) property. Each control belongs to a communication space, by default to ID 0 (zero). Also each socket created by the client side communication manager Ucm.exe, belongs to a communication space, namely to the space of the control, that caused the socket to be established. With one exception (explained below), input messages are not distributed across communication space boundaries. Since only one connection to a given address may exist in each space, all controls referring the same TCP address and CommID share one single connection. In local communication, the CommID of the sending control identifies the target space. It is important to note, that communication spaces are system local entities. The server does not need to know to which space the other end of the socket belongs to. The CommID property should be set prior to the first output operation. A perfect value is the ID of the main thread of a process, since it is guaranteed to be unique:

Sub Form1_Load()
    Ucm1.CommID = App.ThreadID
    Ucm1.AdrMode = ucmService
    Ucm1.Service = "payroll"
    Ucm1.InputID = "form1"
    Ucm1.OutputID = "form1"
    Ucm1.Delimiter = ":"
End Sub


Although making little sense, it is possible to change the CommID of a control at runtime. If in the new space no socket with the same address already exists, the space membership of the existing socket is changed to the new ID. If such a socket already exists, the control is attached to it and the connection left in the old space is closed.

Important note:

If two controls in the same process refer to the same TCP address but have distinct CommID settings, each of the controls communicate with a separate server tread or process. Since this is not what normally is wanted, all CommIDs in a single program should be set to the same value.


5.3.4. Global Communication Space

The default value of the CommID(P) property is 0 (zero), which identifies the global communication space. Unbound UCM controls in the global space will receive messages from all communication spaces if their InputID(P) property value matches the ID of the message that has to be forwarded by the communication manager Ucm.exe. Upon message arrival, the sender address information can be retrieved in the InputCommID(P), InputHost(P), InputPort(P) and InputService(P) properties. When using the wildcard InputID(P) value "*", the message ID is available in the InputMsgID(P) property.

The global communication space mimics the UCM pre 2.0 release behavior.

5.3.5. Terms

This was a lot of new information. Before proceeding to the Active-X reference sections, the definition of some terms will help to understand the concept of UCM communication and its addressing methods. These terms will be used throughout the Property, Event and Method manual pages.

Term Description
message ID Each UCM message is identified by an ID with data type string. Sending a message requires the OputputID(P) property to be set, whose value will become the message ID. To enable a control to receive UCM messages, the InputID(P) property must be set. Only messages that match this value will be received (i.e. will cause an DataInput(E) event to be fired). The special wildcard value "*" matches any ID.
message data To launch a message transfer, the contents data must be assigned to the OutputMsg(P) property. If the AutoSend(P) property is set to True, transfer is immediate, otherwise the Send(M) method must be used to initiate the send operation. The value of an incoming message is available in the InputMsg(P) property whenever a DatInput(E) event occurs.
message field UCM messages are optionally subdivided into fields. The field delimiter can be set in the Delimiter(P) property. Individual field values may be accessed with the Field(M) method and the number of fields contained in an input message is available in the NoOfFields(P) property.
bound control An UCM control is said to be bound if one of the following is true:
unbound control An Ucm control is said to be unbound, if it is not bound (see above). Output operations of unbound controls are local only.
communication space Each control operates within the context of a communication space, which is identified by the CommID(P) property. Also each socket established by the communication manager is attached to a communication space, namely the space the control belongs to, that caused the socket to be created. Message forward occurs only within the given space. This enables multiple copies of the same client program to each communicate with its own server process or thread.
global space The global communication space is identified by ID 0 (zero). Unbound controls will receive input messages from any space when their InputID(P) matches the ID of the message to be distributed.
5.4. AutoStart Processes

With the help of the configuration utility UcmConf(U) automatic program startup on message arrival can be defined. Each entry in the AutoStart table defines a message type (InputID) and the full path to the executable that will handle that message. Whenever a message (local or remote) has to be delivered, and no active UCM control is currently ready to receive that message type (i.e. has its InputID property set to the type in question), the communication manager scans the AutoStart table for a matching entry. If an entry is found, the program specified is started automatically. One of the first actions an AutoStart program must perform, is to initialize an UCM control with the required InputID. Failing to do so may lead to multiple invocations of the same program and to undeliverable messages that will be silently discarded.

5.5. Closing an UCM Connection

UCM connections are dropped automatically when the last Active-X control object using the socket exits, i.e. when the container of the control terminates.

5.6. UCM Error Handling

When an error occurs, UCM controls fire the Error(E) event. Why does UCM not use the Err object and the error trapping methods built into the VB language? Communication errors are not immediate, an application program just initiates operations that are handled asynchronously by UCM. Waiting for each communication request to terminate would lead to unacceptable slow programs. All error events will thus happen unsolicited.

Communication errors must normally be considered as severe. The situation can be compared to memory allocation failures, where in almost all cases, there exists no reasonable way to continue execution of a program. The same holds true for UCM errors.

Since multiple UCM controls may be using the same communication link, all of them might receive the same Error(E) event, e.g. when a connection is dropped by the remote process. Error handling in such situations is a little bit tricky, since you must prevent multiple user notifications for the same error. The code involved might look like this:

Option Explicit

Public g_ucmError as Boolean

Public Sub UcmError(ByVal ErrNumber As UcmOcx.ucmErrors, _
                    ByVal ErrText As String)
    If (g_ucmError) Then
        Exit Sub
    End If
    g_ucmError = True
    If (ErrNumber = ucmErrHost _
    Or  ErrNumber = ucmErrServiceUnknown) Then
        Call MsgBox("No connection could be established." & vbCr & _
                    "Please verify your host or port configuration.", _
                    vbInformation, "UCM Error")
        Call TermApp    ' terminate application
        Exit Sub
    End If
    If (ErrNumber = ucmErrMngrShutdown) Then
        Call MsgBox("The UCM manager has been stopped!" & vbCr & _
                    "Please restart your program.", _
                    vbInformation, "UCM Error")
        Call TermApp    ' terminate application
        Exit Sub
    End If
    Call MsgBox("A communication error has occurred!" & vbCr & _
                "Please close your program and restart.", _
                vbInformation, "UCM Error")
    Call TermApp    ' terminate application
End Sub


Once the public g_ucmError flag is set, UCM output should be avoided. This is best done by wrapping output operations like this:

    If (Not g_ucmError) Then
        Ucm1.OutputMsg = "some output"
    End If


As a final step, implement error event handling for each control:

Private Sub Ucm1_Error(ByVal ErrNumber As UcmOcx.ucmErrors, _
                       ByVal ErrText As String)
    Call UcmError(ErrNumber, ErrText)
End Sub
 

Back to top