home *** CD-ROM | disk | FTP | other *** search
- async1 Example
-
-
-
-
- 1. Environment
-
- This example is designed to be built and executed on a PC
- that runs DOS, the Microsoft C Compiler and utilities, and
- that uses the NetWare network library.
-
-
-
-
- 2. Overview
-
- This example is similar to the async example, but adds a
- feature that allows the client to issue multiple
- asynchronous remote procedure calls to different servers.
-
-
-
-
- 3. Keywords
-
- asynchronous, non-blocking, Hooks, Traps, RPC macros,
- polling, import statement
-
-
-
-
- 4. Files
-
- Source files for this example reside in the following sub-
- directories:
-
- server:
-
- Contains code and build procedures for the server part
- of this distributed application. The server consists
- of the server control procedure, which is provided with
- the product distribution, the dispatcher procedure and
- server stub routines, which are generated by the RPC
- Compiler, and the remote procedures, which are provided
- with this example.
-
- rproc.c remote procedure application code
-
- server.mk makefile for building the server
-
- serv_def.h include file with macro definitions for
- the server control procedure
-
- client:
-
- Contains code and build procedures for the client part
- of this distributed application. The client consists
- of the client main program and any associated routines,
- which are provided with this example, and the client
- stubs, which are generated by the RPC compiler.
-
- client.c client application code (main program)
-
- client.mk makefile for building the client
-
- common:
-
- Contains the RPC interface specification used by the
- RPC compiler to create the client and server stubs.
- The RPC interface specification imports the
- asynchronous RPC specification file to provide the
- asynchronous interface.
-
- async1.rpc RPC interface specification for this
- example
-
- async1:
-
- Contains the RPC interface specification consisting of
- client stub Hooks and Traps code and the source code
- for poll_reply, which provide for an asynchronous
- interface.
-
- async1_i.rpc asynchronous RPC specification and
- polling routine
-
- async1_i.mk makefile for building the asynchronous
- object files and include file
-
- Note that the RPC Compiler is run only once with this
- RPC specification file as input. Generally, the
- Compiler should be run with the file twice: once for
- the client and once for the server, producing header
- files and RPC code files for each. However, for this
- example the procedure is simplified because the single
- header file produced can be used by both the client and
- the server, the RPC Compiler is told to run in client
- mode, and the only application code in the file is for
- the client.
-
-
-
-
- 5. Network Configuration
-
- Before you can run this example, you may have to ask your
- system administrator to configure your system specifically
- for your needs. The required configuration is described in
- the file: ..\..\READSPX
-
-
-
-
- 6. Server Name
-
- As distributed, the server for this example will register
- under the name "example". However, it is strongly suggested
- that a unique server name be assigned to this example before
- it is built.
-
- A unique server name will prevent two or more users from
- invoking a server process using the same server name.
- Choose a server name not likely to be selected by someone
- else. For example, use your user or login name.
-
- The server name must be changed in both the client and the
- server, and the SAME name must be used. To change the
- server name for the client program, change to the client
- directory (client) and edit the file client.c. Change the
- #define Server_Name statement as follows:
-
- #define Server_Name "example"
- is changed to
- #define Server_Name "myname"
-
- To change the server name for the server program, change to
- the server directory (server) and edit the file serv_def.h,
- which contains the define statements for the server control
- procedure. As with the client program, simply change the
- #define Server_Name statement.
-
-
-
-
- 7. Building Client & Server
-
- Procedures are included for building the example program.
- These procedures assume that your environment is set up as
- follows:
-
- - The PATH environment variable must specify the location
- of the RPC Compiler executable files.
-
- - The LIB environment variable must specify the location
- of the RPC runtime libraries.
-
- - The INCLUDE environment variable must specify the
- location of the RPC .h include files.
-
- - The PDUDIR environment variable must specify the
- location of the RPC .rpc files.
-
- - The RPCSCP environment variable must specify the
- location of the RPC server control procedures.
-
- The PATH, LIB, and INCLUDE environment variables should be
- set in your autoexec.bat file by modifying their current
- definitions. The PDUDIR and RPCSCP environment variables can
- be set in your autoexec.bat file, or in a local .bat file,
- or directly with the "set" command.
-
- Since a distributed application runs on two machines, you
- must install an executable version of the client or server
- on another machine. If the two machines are identical, you
- can build both executables (the client and server) on one
- machine and then move one of the executables. However, if
- the two machines are not identical, you must follow the
- directions on the other machine for running this example and
- build one of the executable programs there (note that the
- executable filenames may differ across products).
-
- Note that with the Microsoft C Compiler and utilities,
- numerous warnings will be generated when executing the
- makefiles. For example, you may see a "target does not
- exist" or "module not in library" warning. These simply mean
- that the file the makefile is currently creating does not
- yet exist. Generally, all warnings may be ignored.
-
- To build the example program, you simply execute the build
- procedures in each subdirectory as follows:
-
- 1. Change to the async1 directory and build the files
- associated with the imported RPC specification file:
-
- make async1_i.mk
-
- 2. Change to the client directory (client) and build the
- client:
-
- make client.mk
-
- 3. Change to the server directory (server) and build the
- server:
-
- make server.mk
-
-
-
-
-
- 8. Running the Distributed Application
-
- The server program should be started before the client
- program is run.
-
- To run the example on two machines, proceed as follows:
-
- 1. Change to the server directory (server) on the machine
- running the server and start the server:
-
- server
-
- 2. Change to the client directory (client) on the machine
- running the client and start the client:
-
- client
-
-
-
-
-
- 9. Description
-
- This example demonstrates a client that uses a non-blocking
- RPC interface. Using this interface, the client can
- generate an RPC request and continue executing until the RPC
- reply is returned by the server. Once the reply is
- received, the client can then obtain the results returned by
- the remote procedure.
-
- To facilitate the use of this style of asynchronous client
- interface, this example separates the non-blocking client
- code into a special RPC specification called "async1_i.rpc."
- This RPC specification contains Hooks and Traps statements
- to customize client stubs so that they do not block for
- replies. Thus, by importing "async1_i.rpc" within an RPC
- specification, all client stubs generated from this
- specification provide an asynchronous client interface to
- the described remote procedures.
-
- Once the client stubs have been customized to incorporate
- the asynchronous code, the client can call a client stub to
- generate a request and send this to the server. Having
- initiated the remote procedure, the client stub returns to
- the client code so that this code can continue execution.
- Once the reply has been received, the client code can once
- again call the client stub. This second call to the client
- stub receives the reply, unpacks the results, and returns
- these results to the client code. To ensure that the
- results are handled properly, the client code must call the
- client stub twice with exactly the same parameters.
-
- Unlike the "async_i.rpc" specification shown in the async
- example, the "async1_i.rpc" specification customizes client
- stubs so that information about expected reply messages is
- stored in dynamically allocated memory referenced by a
- parameter passed to and returned by every client stub. This
- parameter, called "cli_rpc_handle", must be declared as a
- pointer to a character pointer and must be declared as a
- parameter within every client stub. By using these
- parameters, the client can issue several RPC requests
- simultaneously to different servers and continue executing
- until any of the replies are detected.
-
- To assist in determining when the reply has been received,
- the "async1_i.rpc" specification is accompanied by an object
- module containing a routine called poll_reply. This routine
- is declared as follows:
-
- int poll_reply(char *rpc_handle)
-
- Whenever poll_reply is called, this procedure must be passed
- a character pointer initialized by a call to a client stub.
- The poll_reply procedure then determines the status
- concerning the reply associated with the remote procedure
- call identified by the rpc_handle parameter. The poll_reply
- procedure then returns an integer value.
-
- A value of 1 means that a reply has been received; call the
- stub again with exactly the same parameters as before.
- A value of 0 means that a reply has not been received yet;
- continue as before, but do not call the stub yet.
- An error code value means that an error was detected; call
- the stub again with exactly the same parameters as before so
- the state machine can clean up.
-
- Using the poll_reply procedure, the client can determine
- when to call the client stub procedure again in order to
- handle the reply sent by the server.
-
- Note that, unlike the async example, the client can use this
- interface to issue several RPC requests simultaneously.
- However, there is no guarantee that any one server can
- handle more than a single pending RPC request from the
- client. Thus, to ensure proper interaction, the client must
- only issue one RPC request at a time to a single server.
-
- Further note that a server requires no special modifications
- to interact with an asynchronous client. In fact, the same
- server may interact with both synchronous and asynchronous
- clients.
-
- However, the RPC specification for the application does
- require modification. In order to pass the RPC state
- information to the client stub (in the "cli_rpc_handle"
- variable), the RPC specification that declares the remote
- procedures must specify that an extra parameter is being
- "passed" to each remote procedure. Then, using Entry and
- Exit statements in the client stub customization code, the
- client stub can access that parameter. Note that, in fact,
- the parameter is passed to each remote procedure, but it can
- safely be ignored, as its only use is in the client stub
- code.
-
- For more information on adding custom code, see the
- NetWare RPC User's Manual, "Customizing the RPC Code,"
- Chapter 7.