UCM Unitec Home Page
      

Chapter 9 - Programming

 

9.1. Overview
9.2. C-Language Interface
9.3. Cobol Interface Parameters
9.4. Cobol Interface Functions

9.1. Overview

This chapter serves as reference to the software developer wanting to utilize the communication services of UCM.

Section 9.2 shows some examples on how to use the C-Language Interface.

9.2. C-Language Interface

In this section three different server models are shown:

  • Standard Server
  • Self-Contained Server
  • Inetd Server

All of these servers do the same processing, they just write back the messages received. The purpose of this section is to show how to implement and configure UCM servers, but not application dependent message processing.

To test all of these examples, a simple C or Visual Basic program can be made:

C Client

/* UCM Client / ucmtest.c */

#include "ucm.h"

main(argc, argv)

int argc;
char *argv[];
{
    int len;
    T_SOCKET sock;
    T_UCM_MSGID msgId;
    T_UCM_MSG msg;

    ucmProgName = "UcmTest";         /* for UCM error messages */
    UcmInit();
    sock = UcmConnect("128.41.1.1", "7999");
    if (sock < 0)
    {
        fprintf(stderr, "UcmConnect failed, ucmErrno=%d\n", ucmErrno);
        return 1;
    }
    UcmSendf(sock, "Test", "Hello World!");
    if ((len = UcmRecv(sock, msgId, msg, -1, UF_NOFLAGS)) > 0)
        printf("From server: ‘%s’\n", msg);
    UcmClose(sock);
    UcmTerm();
    return 0;
}


Visual Basic Client

Create a project and use the Project | Components... dialog to add the UCM Active-X Control, Ucm.ocx, located in your Windows system directory, to the new project.

On Form1 (the main form) place two label controls, two text controls, two button controls, and an UCM control. Your form should now lock like this:

UcmVbFrm1.gif (3194 bytes)

Set the properties of the new controls as follows:

Property Value
Form1.Caption UCM Test
Label1.Caption Output:
Label2.Caption Input:
Text1.Text <blank>
Text2.Text <blank>
Command1.Caption &Send
Command2.Caption E&xit
Ucm1.AdrMode ucmTCP
Ucm1.Host 128.41.1.1 / use correct IP address of your UCM server system
Ucm1.Port 7999
Ucm1.InputID Test
Ucm1.OutputID Test


Now your form locks like:

UcmVbFrm2.gif (3076 bytes)

To finish the test program, you have to add event logic:

Command1_Click()

Ucm1.OutputMsg = Text1

Command2_Click()

Unload Me

Form1_Unload(Cancel as Integer)

Ucm1.OutputMsg = "Exit"

Ucm1_DataInput()

Text2 = Ucm1.InputMsg

As a final step, use File | Make EXE File... to create the ucmtest.exe program. You have just created an UCM client application in less than five minutes!

Configuration is easy as well. Throughout this section we use TCP/IP service ID 7999. If this number is already in use, select any number greater than 5000. It is however important, that the same ID is used on both, the server and the client systems.

Important note:

In TCP/IP programming a communication link between a server and a client is established by the use of a entity called socket, introduced by UCB University of California at Berkley, also referred to by 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 rage from 1 to 1023, but room should be kept for extension. 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.


Your new UCM client application is now ready to run. But wait, before the test run starts, the server program has to be developed on the host.

A) Standard Server

/* Standard UCM Server */

#include "ucm.h"

static T_SOCKET sock;
static T_UCM_MSGID msgId;
static T_UCM_MSG   msg;


main(argc, argv)

int argc;
char *argv[];
{
    int len;

    if (argc < 2 || (sock = atoi(argv[1]) < 1))
    {
        fprintf(stderr, "illegal socket argument\n");
        return 1;
    }
    ucmProgName = argv[0];    /* for UCM error messages */
    UcmInit();
    if (UcmOpen(sock))
    {
        fprintf(stderr, "UcmOpen failed, ucmErrno=%d\n", ucmErrno);
        return 1;
    }
    while ((len = UcmRecv(sock, msgId, msg, -1, UF_NOFLAGS)) > 0)
    {
        /* process incoming message */
        if (strcmp(msg, "Exit") == 0)
            break;
        UcmSendf(sock, msgId, "Got: %s", msg);
    }
    UcmClose(sock);
    UcmTerm();
    return 0;
}


Compile with: cc -o test1 test1.c libucm.a

Start the new server manually with:

UcmServer -s 7999 -e test1

Now you can switch to Windows and run ucmtest.exe. Enter ‘Hello World!’ in the Input box and push the Send button. You should now see ‘Got: Hello World’ in the Output box. To stop the program, push the Exit button.

Back to Unix, use the ps(1) command and locate the UcmServer process. Use the numeric process ID (PID) to stop the server with kill(1)

kill <PID>

B) Self-Contained Server

/* Self-Contained UCM Server */

#include "ucm.h"

#if defined(__STDC__)
static int DoService(T_SOCKET sock);
#else
static int DoService();
#endif


main(argc, argv)

int argc;
char *argv[];
{
    ucmProgName = "test2";    /* for UCM error messages */
    UcmInit();
    UcmServer("7999", DoService);
    UcmTerm();
}

static int DoService(sock)

T_SOCKET sock;
{
    int len;
    T_UCM_MSGID msgId;
    T_UCM_MSG   msg;

    if (UcmOpen(sock))
    {
        fprintf(stderr, "UcmOpen failed, ucmErrno=%d\n", ucmErrno);
        return 1;
    }
    while ((len = UcmRecv(sock, msgId, msg, -1, UF_NOFLAGS)) > 0)
    {
        /* process incoming message */
        if (strcmp(msg, "Exit") == 0)
            break;
        UcmSendf(sock, msgId, "Got: %s", msg);
    }
    UcmClose(sock);
    return 0;
}


Compile with: cc -o test2 test2.c libucm.a

Start the new server manually with:

test2

Again, you can use this server with the Windows ucmtest.exe client.

To stop the server, use the ps(1) command and locate the test2 process. Use the numeric process ID (PID) to stop the server with kill(1).

C) Inetd Server

/* Inetd UCM Server */

#include "ucm.h"

static T_SOCKET sock;
static T_UCM_MSGID msgId;
static T_UCM_MSG   msg;


main(argc, argv)

int argc;
char *argv[];
{
    int len;

    sock = 0;                 /* stdin, stdout and stderr all point to the
                              ** socket descriptor we may use.
                              */
    ucmProgName = argv[0];    /* for UCM error messages */
    UcmInit();
    if (UcmOpen(sock))
        return 1;
    while ((len = UcmRecv(sock, msgId, msg, -1, UF_NOFLAGS)) > 0)
    {
        /* process incoming message */
        if (strcmp(msg, "Exit") == 0)
            break;
        UcmSendf(sock, msgId, "Got: %s", msg);
    }
    UcmClose(sock);
    UcmTerm();
    return 0;
}


Compile with: cc -o test3 test3.c libucm.a

The Internet Superserver inetd(1) requires to use symbolic service names as defined in the services file.

Edit your /etc/services file and add the same lines as on the client system:

# UCM Services
ucmtest 7999/tcp

Now edit your /etc/inetd.conf file and add the lines:

# UCM Services
ucmtest stream tcp nowait root /usr/ucm/test3

The inetd(1) process reads configuration file /etc/inetd.conf at startup to initialize itself. This will also make our ucmtest service available for connections through ucmtest.exe on the Windows client.

As shown in this section, writing UCM server- as well as client applications is very easy and provides fast development cycles.

9.3. Cobol Interface Parameters

The Unix distribution media of UCM contains a Cobol copy book and an interface library in source. These files enable programmers to implement Cobol UCM servers. Since many different Cobol flavors exist, some adaptations may be necessary. The functions have been tested to work with MF Cobol. Other environments will likely need some changes in the area of parameter passing to functions (see Calling Conventions in your Cobol documentation).

The copy book is named uci.cpy:

*-----------------------------------------------------
* Unitec Communication Manager Copy-Book
* **************************************
*
* Parameter:
*
* UCI-PAR:
* - UCI-SOCKET:   Socket-No. from 'ucmserver'
* - UCI-ERRNO:    Error-No. if return code <> 0
*
* UCI-ADDR:
* - UCI-HOST:     Host IP address or host name
* - UCI-SERVICE:  TCP/IP service name or port no.
*
* UCI-MSG:
* - UCI-IDSIZE:   Length of the message ID buffer
* - UCI-MSGSIZE:  Length of the message buffer
* - UCI-MSGLEN:   Length of the current input message
* - UCI-IDBUF:    Message-ID value
* - UCI-MSGBUF:   Message value
*
* UCI-RELEASE:
* - UCI-TIMEOUT:  UciClientVersion timeout in ms
* - UCI-VERSION:  Version number
*
*-----------------------------------------------------

 01      UCI-PAR.
     05  UCI-SOCKET     PIC 9(5) VALUE 0.
     05  UCI-ERRNO      PIC 99.
*
 01      UCI-ADDR.
     05  UCI-HOST       PIC X(32).

     05  UCI-SERVICE    PIC X(32).
*
 01      UCI-MSG.
     05  UCI-IDSIZE     PIC 9(2) VALUE 32.
     05  UCI-MSGSIZE    PIC 9(4) VALUE 2000.
     05  UCI-MSGLEN     PIC 9(4).
     05  UCI-IDBUF      PIC X(32).
     05  UCI-MSGBUF     PIC X(2000).
*
 01      UCI-RELEASE.
     05  UCI-TIMEOUT    PIC 9(5) VALUE 10000.
     05  UCI-VERSION    PIC 9(4).
*
* End 'uci.cpy'


The values of UCI-IDSIZE and UCI-MSGSIZE must correspond to the size of UCI-IDBUF and UCI-MSGBUF respectively. The maximum values are described under Configuration Limits, Chapter 10.

9.4. Cobol Interface Functions

This section contains descriptions of the UCM Cobol Interface function family UCI. Users of UCM Rel 1.x may also use the compatibility layer grouped in the UDM function family. For a description of the UDM functions, please refer to the Rel. 1.x manual. The page headers for each description contain the function name and title.

The Synopsis section gives a summary of the actual function declaration.

The Description explains all of the function's operational details.

In the Diagnostics section, common status and error codes are listed, often with possible explanation for their occurrences.

Related functions are identified in the See Also section.

An Example section is provided for each function. The example is intended to illustrate how the function is called, not necessarily how to use the function. In some cases, the example is very brief. In all cases, it should be sufficient to show how the call is made.

The following functions are in alphabetical order:

Function Title
UciClientVersion Get software version of UCM client.
UciClose Close UCM Connection.
UciConnect Open UCM connection (Client).
UciInit Initialize Communication.
UciOpen Open UCM connection (Server).
UciRead Receive Client Message.
UciTerm Terminate Communication.
UciVersion Get UCM library software version.
UciWrite Send Message to Client.


Return- and error codes of all UCI functions are described in ucmErrno.

Although most of the UCM clients make use of the Active-X control Ucm.ocx, the following table shows the control flow of a typical Cobol only client-server session:

Server Client
Start server through UcmServer(U)  
  Call UciInit
Call UciConnect
Call UciInit
Accept socket from command line
Call UciOpen
 
  Call UciWrite [1]
Call UciRead, receive message [1]
Call UciWrite [2]
 
  Call UcmiRead, receive message [2]
Repeat read/write as needed Repeate write/read as needed
Call UciClose
Call UciTerm
Call UciClose
Call UciTerm
 

Back to top