MPE/iX 5.0 Documentation
Net IPC 3000/XL Programmer's Reference Manual
Using NetIPC for Interprocess Communication
The following paragraphs describe the tasks for using NetIPC for
process-to-process communication in programs which are:
* Establish a connection.
* Send and receive data over the connection.
* Shut down the connection.
These discussions are based on access to level 4 (TCP) but most
principles apply to direct access to level 3 (X.25). Information
specific to X.25 is noted in the discussion.
After establishing a virtual circuit, you can use other NetIPC functions
which are described in this chapter under the heading, "Additional NetIPC
Functions".
Establishing a Level 4 Connection
The following paragraphs are a call-by-call explanation of the dialogue
through which a virtual circuit connection is built. This example uses
the socket registry facility by establishing names for call sockets with
IPCNAME and retrieving the names with IPCLOOKUP. Figure 1-9 shows the
sequence of calls to use if the address of the socket is known (using
IPCDEST).
Only two processes are shown in this example. Either or both of the
processes shown can establish virtual circuit connections with other
processes. Secondary or auxiliary connections can also be set up between
the same two processes.
NOTE Both of the processes in the following dialogue are assumed to be
created and running at their respective nodes. NetIPC does not
include a call to schedule remote processes. Refer to the chapter,
Remote Process Management, in the Using NS3000/XL Network Services
manual for more information about initializing remote processes
with RPM.
1. Creating a Call Socket. Interprocess communication is initiated when
Process A and Process B each create a call socket by invoking the NetIPC
call IPCCREATE (see Figure 1-2). As explained previously, a call socket
is roughly analogous to a telephone with multiple extensions (see Figure
1-1). IPCCREATE returns a call socket descriptor to the calling process
in its calldesc parameter that describes the call socket, or "telephone
extension," that the process has created. This call socket descriptor is
then used in subsequent NetIPC calls.
Figure 1-2. IPCCREATE. (Processes A and B)
2. Naming a Call Socket. Process B associates a name with its call
socket by calling IPCNAME (see Figure 1-3). When a call socket is named,
this information is placed in the socket registry at the local node. The
name Process B assigns to its call socket must also be known to Process A
because Process A must reference it later in its IPCLOOKUP call. (When a
socket name is known to both processes in this way, it is called a
well-known name.) Although call sockets do not have to be named, a
process cannot gain access to the socket of another process if the socket
is not named (unless the address of that socket is known, in which case
IPCDEST is used). The socket must be named and be recorded in the socket
registry at the node of Process B when Process A calls IPCLOOKUP.
Figure 1-3. IPCNAME. (Process B)
3. Looking Up a Call Socket Name. Process A must reference the call
socket of Process B by its name in the call to IPCLOOKUP to "look up" the
name of the call socket in the socket registry at the node where Process
B resides. IPCLOOKUP returns a destination descriptor in its destdesc
parameter (see Figure 1-4). The destination descriptor indicates the
location of the destination call socket which is owned by Process B.
IPCLOOKUP is similar to a telephone company's directory assistance
service: Process A calls the "operator" (IPCLOOKUP), and gives him/her a
"city" ( location parameter) and a "name" ( socketname parameter). Using
the "city," that is, the node name or environment ID, the operator looks
for the name in the proper "telephone directory" (socket registry). Once
the name is found, the operator returns a "telephone number" ( destdesc
parameter) to the caller.
Figure 1-4. IPCLOOKUP. (Process A)
4. Requesting a Connection. Process A specifies the destination
descriptor returned by IPCLOOKUP and the call socket descriptor returned
by IPCCREATE in its IPCCONNECT call. With these two parameters,
IPCCONNECT requests a virtual circuit connection between Process A and
Process B (see Figure 1-5). This could be compared to dialing a phone
number. IPCCONNECT then returns a VC socket descriptor in its vcdesc
parameter that describes the VC socket endpoint of the connection at
Process A.
Figure 1-5. IPCCONNECT. (Process A)
5. Receiving a Connection Request. Using the call socket descriptor
returned by its IPCCREATE call, Process B calls IPCRECVCN to receive any
connection requests. In this example, Process B receives a connection
request from Process A. (Process A "dialed its telephone" to call Process
B when it called IPCCONNECT.) IPCRECVCN returns a VC socket descriptor in
its vcdesc parameter (see Figure 1-6). This VC socket is the endpoint
of the virtual circuit at Process B. The connection will not be
established, however, until Process A calls IPCRECV. In the telephone
analogy, IPCRECVCN is similar to picking up a ringing phone and saying
"hello".
Figure 1-6. IPCRECVCN. (Process B)
6. Checking the Status of a Connection. Process A calls IPCRECV using
the VC socket descriptor returned by its IPCCONNECT call. IPCRECV
returns the status of the connection (successful/unsuccessful) initiated
by IPCCONNECT. If the status is successful, the connection has been
established and Process A and Process B can "converse" over the new
virtual circuit (see Figure 1-7). Compared to the telephone system,
IPCRECV is similar to saying "hello" in response to the "hello" from the
other end of the phone. IPCRECV can also be used to receive data. This
function is described in the IPCRECV call discussion later in this
section.
Figure 1-7. IPCRECV. (Process A)
Connection Establishment Summary. The following discussions summarize
the methods for establishing connections using NetIPC intrinsics.
Connection Establishment Using IPCNAME. Figure 1-8 illustrates the
sequence of NetIPC calls that is used to establish a virtual circuit
connection. This figure summarizes the information presented in Figures
1-2 through 1-7.
Figure 1-8. Establishing a Connection (Summary)
Connection Establishment Using IPCDEST. Figure 1-9 illustrates the
sequence of NetIPC calls that is used to establish a virtual circuit
connection when the protocol relative address of the remote node is
known.
Figure 1-9. Using IPCDEST>
Sending and Receiving Data Over a Connection
Once a virtual circuit connection is established, the two processes can
exchange data using the NetIPC calls IPCSEND and IPCRECV. Either process
can send or receive data. IPCSEND is used to send data on an established
connection; it is analogous to "speaking" over a telephone connection.
IPCRECV is used to receive data on an established connection; the use of
IPCRECV is similar to "listening" at our telephone handset. (Note that
IPCRECV has a dual function: to complete a virtual circuit connection as
well as to receive data on a previously established connection.)
X.25 Access. Direct access to level 3 (X.25) provides message mode
transfer. Stream mode is not supported for X.25. Each IPCRECV returns a
complete message (provided the data length specified is of sufficient
size). The X.25 protocol signals the end of message and NetIPC buffers
the message until an IPCRECV (or required IPCRECVs), retrieve it.
TCP Access. For TCP access, all data transfers between user processes
are in stream mode. In stream mode, data is transmitted as a stream of
bytes with no end-of-message markers. This means that the amount of data
received in an individual IPCRECV is not necessarily equivalent to the
amount of data sent in an IPCSEND call. In fact, the data received may
contain part of a message or even several messages sent by multiple
IPCSEND calls.
You specify the maximum number of bytes you are willing to receive
through a parameter of IPCRECV. When the call completes, that parameter
contains the number of bytesactually received. This will never be more
than the maximum amount you requested, but it may be less. The data you
receive will always be in the correct order (in the order that the
messages were sent), but there is no indication of where one message ends
and the next one starts. It is up to the receiving process to check and
interpret the data it actually receives. An application which does not
need the information in the form of individual messages can simply
process the data on the receiving side.
If an application is concerned about messages, the programmer must devise
a scheme that allows the receiving side to determine what the messages
are. If the messages are of a known length, the receiving process can
execute a loop which calls IPCRECV with a maximum number of bytes equal
to the length of the portion of the message not yet received.
Since IPCRECV returns to you the actual number of bytes received, you can
continue to execute the loop until all the bytes of the message have been
received. The following Pascal program fragment demonstrates this idea:
received_len := 0;
while (received_len < msg_length) and (errorcode = 0) do
begin
data_len := msg_length - received_len;
ipcrecv( connection, tempbfr, data_len,,,errorcode );
if errorcode = 0
then strmove(data_len,tempbfr,1,databfr,
received_len+1);
received_len := received_len + data_len;
end;
In the above example, the Pascal function strmove takes each piece of the
message received in tempbfr and concatenates it to the portion of the
message already in databfr. Upon exiting the loop, the entire message
has been stored in databfr. If the length of the messages are not known,
the sending side could send the length of the message as the first part
of each message. In that case, the receiving side must execute two
IPCRECV loops for each message: first to receive the length and then to
receive the data. An example of this technique is shown at the end of
this section.
Shutting Down Sockets and Connections
The NetIPC call IPCSHUTDOWN releases a descriptor and any resources
associated with it. IPCSHUTDOWN can be called to release a call socket
descriptor, a destination descriptor, or a VC socket descriptor. Because
system resources are being used whenever descriptors exist, you should
probably release them when they are no longer needed.
The call socket is needed as long as a process is expecting to receive a
connection request on that socket. A process which receives a connection
request can release the call socket any time after the IPCRECVCN
connection request, as long as no other connection requests are expected
for that call socket.
Similarly, a process which requests a connection can release its call
socket any time after the call to IPCCONNECT, as long as it is not
expecting to receive any more connection requests for that socket.
For TCP only, a process does not need to create a call socket (via
IPCCREATE) at all; instead, it can use a temporary call socket by calling
IPCCONNECT without specifying a call socket descriptor. (A temporary
call socket is automatically destroyed when the IPCCONNECT call
completes.) A process which requests a connection can also release the
destination socket any time after the call to IPCCONNECT.
For example, in the section "Establishing a Connection", Process A no
longer needs the destination descriptor after calling IPCCONNECT and can
use IPCSHUTDOWN to release the destination descriptor. In addition, if
Process A does not expect to request additional connections, it can also
call IPCSHUTDOWN a second time to release the call socket.
Process B, as described in "Establishing a Connection", can call
IPCSHUTDOWN to release its call socket any time after the call to
IPCRECVCN (see "Receiving a Connection Request"). Process B should
release its call socket only if it does not want to establish additional
connections.
Before a process terminates, it should terminate its virtual circuit
connections by releasing its VC sockets with IPCSHUTDOWN. If a process
does not release its VC sockets before terminating, the system releases
them when the process terminates. Because IPCSHUTDOWN takes effect very
quickly, all of the data that is in transit on the connection is lost
when the connection is shut down. As a result, if there is a possibility
that data is in transit on the connection, the processes that share a
connection must cooperate to ensure that no data is lost.
X.25 Access. X.25 direct access to level 3 does not support the
graceful release bit. Using IPCSHUTDOWN on a VC socket descriptor causes
a clear packet to be sent.
To ensure that no data packets are lost before the clear packet is sent,
the D bit option can be set in the last IPCSEND. This assures end-to-end
acknowledgement of this message before issuing the IPCSHUTDOWN to clear
the virtual circuit.
Another method to ensure no lost packets is to send an unimportant
message as the last message. The following example shows the calling
sequence you would use. Note that the "dummy" message may or may not be
received by the last IPCRECV. If the last message is not received, a
SOCKERR 67 "CONNECTION FAILURE DETECTED" is returned.
IPCSEND ----> IPCRECV
(important message) (important message
received)
<---- IPCSEND
(dummy message sent)
IPCRECV
(receive dummy IPCSHUTDOWN
message)
IPCSHUTDOWN
TCP Access. To ensure that no data is lost, the IPCSHUTDOWN graceful
release bit can be set, and the following sequence of steps can be
followed:
Process A calls IPCSHUTDOWN and sets bit 17, the graceful release flag.
Process B receives a message (with an IPCRECV) informing it that Process
A has called for graceful release. (This message is sent to B
automatically when A sets the graceful release flag.) Process A enters
a simplex-in state; meaning, it can receive, but not send, data. Process
B will enter a simplex-out state, that is, it can send but cannot receive
data. As a result, data that is in transit to Process A (which initiated
the graceful release shutdown) will reach Process A without being lost.
Next, one of two steps must occur to completely shut down the connection.
Either (1) Process B initiates with or without its own graceful release
or (2) Process A calls IPCSHUTDOWN without the graceful release option.
This releases Process A's VC socket descriptor and shuts down the
connection. In this case, Process B must also release its socket
descriptor by calling IPCSHUTDOWN.
If the graceful release option is not used (this may be necessary, for
example, if the remote node does not supportgraceful release) the
following steps should be followed when shutting down a connection.
Process A sends a "last message" to Process B via an IPCSEND call. This
message contains data that is recognized by Process B as a termination
request, and may also contain data to be processed by Process B. Process
A then calls IPCRECV.
Process B receives the message from Process A with a call to IPCRECV and
sends a "confirmation message" to Process A via IPCSEND. This message
contains data that indicates to Process A that it is okay to terminate
the connection, and may also contain data to be processed by Process A.
Process B then calls IPCRECV.
Process A receives a "confirmation message" from Process B via the call
to IPCRECV and calls IPCSHUTDOWN to release its VC socket descriptor and
shut down the connection.
The IPCRECV call of Process B completes with a result parameter value of
64 ("REMOTE ABORTED THE CONNECTION"). It then calls IPCSHUTDOWN to
release its VC socket.
Additional NetIPC Functions
Once a virtual circuit is established between processes, descriptors can
be given away, names can be erased, and other functions can be performed.
The following NetIPC calls are provided in addition to those described in
the previous paragraphs to enable you to perform these additional
functions. A brief introduction to each call and its use follows. A
complete description of NetIPC calls is provided in Chapter 3.
* IPCCONTROL. Performs special operations on sockets such as enabling
synchronous mode, and changing asynchronous timeout values.
* IPCDEST. Returns a destination descriptor which can be used to send
messages to another process. This is an alternative to naming the
descriptor with IPCNAME and acquiring it with IPCLOOKUP.
* IPCGET. The companion call to IPCGIVE. Receives a call socket or
virtual connection given away by a process that has called IPCGIVE.
This call is similar to IPCLOOKUP because it enables your process to
acquire a descriptor that can be used in subsequent NetIPC calls.
* IPCGIVE. The companion call to IPCGET. Releases ownership of a
descriptor to NetIPC so that it can be acquired by another process
via a call to IPCGET.
* IPCNAMERASE. Does the reverse of IPCNAME: it removes a name
associated with a call socket from the socket registry. Only the
owner of a call socket descriptor can remove its name.
MPE/iX 5.0 Documentation