|
|
NetIPC 3000/XL Programmer's Reference Manual: HP 3000 MPE/iX Computer Systems > Chapter 1 NetIPC FundamentalsUsing NetIPC for Interprocess Communication |
|
The following paragraphs describe the tasks for using NetIPC for process-to-process communication in programs which are:
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". 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 “Using IPCDEST” 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.
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 “IPCCREATE (Processes A and B)”). As explained previously, a call socket is roughly analogous to a telephone with multiple extensions (see Figure 1-1 “Telephone Analogy”). 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. Process B associates a name with its call socket by calling IPCNAME (see Figure 1-3 “IPCNAME (Process B)”). 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. 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 “IPCLOOKUP (Process A)”). 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. Process A specifies the destination descriptor returned by IPCLOOKUP and the call socket descriptor returned by IPCCREATE in its call. With these two parameters, IPCCONNECT requests a virtual circuit connection between Process A and Process B (see Figure 1-5 “IPCCONNECT (Process A)”). 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. 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 “IPCRECVCN (Process B)”). 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". 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 “IPCRECV (Process A)”). 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. The following discussions summarize the methods for establishing connections using NetIPC intrinsics. <Figure 1-8 “Establishing a Connection (Summary)” illustrates the sequence of NetIPC calls that is used to establish a virtual circuit connection. This figure summarizes the information presented in previous Figures. Figure 1-9 “Using IPCDEST” 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. 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.) 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. 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 bytes actually 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:
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. 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 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 acknowledgment 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.
To ensure that no data is lost, the IPCSHUTDOWN graceful release bit can be set, and the following sequence of steps can be followed:
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 “NetIPC Intrinsics”
|
|