You are on page 1of 8

THE SESSION LAYER

The session, presentation, and application layers form the upper layers in the OS1 Reference Model. In contrast to
the lower four layers, which are concerned with providing reliable end-ta-end comlLunication, the upper layers are
concerned \-vith providing user-oriented services. They take the bare-bones, error-free channel provided by the transport
layer, and add additional features that are useful to a wide variety of upplications, so that the writers of these applications
will not each have to re-implement these features over and over as part of each separate prograrn.
The session layer is basically an invention of ISO. Prior to the OS1 model, no existing network had a session layer
(although some of the OS1 session services are present in SNA, albeit scattered over several layers), During the
a
development of OSI, there was considerable debate about the need for session layer. The British proposal to ISO, for
example, had only five layers and did not include a session layer.
Although a majority of the ISO committee eventually decided to include a session layer, it should be clear from
the brevity of this chapter that the session layer is a "thin" layer, with relatively few features compared to the lower layers.
Furthermore, when a session layer connection is established, options can be selected to disable most of the available
features. It is not nearly as important as, say, the transport layer, and many applications do not need even the few features
that it does have, Nevertheless, it is now part of the OSI Reference Model, so let us turn to l! and see what services it
offers and how they work.
A session bears a close resemblance to a transport connection, but the two are not identical. Usually, when a
request comes into the session layer to establish a session, a transport connection must be established to carry the
connection. When the session is terminated, the transport connection is released. In this example there is a one-to-one
mapping between the session and transport connection.
7.1.1. Services Provided to the Presentation Layer
The session layer provides services to the presentation layer. Its position in the hierarchy is shown in Fig. 7-
1. This figure is analogous to Fig. 6-1, except that the service access points are called session service access points
(SSAPs) and the protocol data units are called session protocol data units (SPDUs). Analogously with the transport
layer, we will use the terms session service provider and session entity interchangeably.
However, other mappings are also possible. Consider the case of an airline with reservation offices in many cities.
Each office has agents with terminals connected to a minicomputer in the local office. The minicomputers are connected
by a wide-area network to the main computer holding the reservation data base. Whenever an agent answers a call, a
session is established to the main computer. When the call has been processed, the session is terminated, but there is no
need to go to the trouble of releasing the underlying transport connection, because it will surely be needed again within a
few seconds. It is simpler to allow sequential sessions to use the same transport connection, as shown in Fig. 7-2(b).
A third possible mapping between sessions and transport connections is given in Fig. 7-2(c). Here we see a
session that spans multiple transport connections. If for example, a transport connection fails (for whatever reason), the
session layer can establish a new transport connection, and continue the session over the new one. If the transport entities
reside in the hosts. this situation should not occur because the transport entities are expected to recover from network layer
(i.e., subnet) failures themselves. However, if the transport entities are external to the hosts, the problem of recovery from
external failures is pushed up to the session layer because it then becomes the lowest layer of software that can survive
subnet crashes.
The main function of the session layer is to provide a way for the session users (e.g., presentation entities or
sometimes just ordinary user processes) to establish connections, called sessions, and transfer data over them in an
orderly way. A session might be used for a remote login from a terminal to a distant computer, or for a file transfer, or
for any of many other purposes. Although connectionless primitives are available in the session layer, a
connectionless session cannot make any use of the user-oriented features for which the session layer was designed.
As an aside, it is not permitted to multiplex several sessions onto a single transport connection simultaneously the
way the transport layer can multiplex several transport connections onto a network connection. At any instant of time, each
transport connection carries at most one session. Multiplexing is done to reduce cost or improve performance, which are
transport layer functions.
7.1.2. Data Exchange

The most important feature of the session layer is data exchange. A session, like a transport connection, goes
through three phases: establishment, use, and release. The primitives provided to the presentation layer for establishing,
using, and releasing sessions are very similar to the primitives provided to the session layer for establishing, using and
releasing transport connections. In many cases, all the session entity has to do when a primitive is invoked by the session
user, is invoke the corresponding transport primitive to get the work done.
For example, when a session user issues an S-CONNECT.request primitive to establish a session, the session
provider just issues a T-CONNECT.request to establish a transport connection (assuming that no transport connection
happens to be available). Similarly, session establishment, like transport connection establishment, involves negotiation
between the peers (users) to set the values of various parameters. Some of these parameters actually pertain to the transport
connection, such as quality of service and the flag telling whether or not expedited data are permitted. These are just
passed to the transport connection without modification. Others are specifically related to the session layer. For example, if
a session is being established between two computers for the purpose of exchanging electronic mail in both directions, one
of the session parameters might specify which side was to go first.
Nevertheless, despite these similarities, important differences do exist between a session and a transport
connection. Chief among these is the way sessions and transport connections are released. Transport connections are
terminated with the T-DISCONNECT.request primitive, which gives an abrupt release and may result in data in transit at the
time of the release being irretrievably lost. Sessions are ended with the S-RELEASE .request primitive, which results in an
orderly release (also called a graceful release) in which no data are ever lost. An abrupt release, like TDISCONNECT.request,
is also available in the form of S-U-ABORT.request.
The difference between an orderly and an abrupt release can be seen in Fig. 7-3.
In the abrupt release, as soon as either user has issued the appropriate primitive to disconnect, no more data can be
delivered to it. In Fig. 7-3(a), once B has invoked T-DISCONNECT.request, its end of the connection is immediately released.
It may not receive the message that is currently in transit for it, even if that message arrives before the DR TPDU arrives at
A. Furthermore, A may not refuse the request to release the connection. The transport service provider just issues a T-
DISCONNECT.indication and that is that. It is like a telephone connection: when one party hangs up, the connection is
terminated, no matter what the other one wants.
Orderly release works differently. It uses a full handshake, with request, indication, response, and confirm primitives.
In Fig. 7-3(b), even after B has issued an S-RELEASE.request primitive, it can still accept messages until A has confirmed the
release. Just issuing an S-RELEASE .request does not terminate the session by itself.

The remote user must agree. If the remote user wants to continue the session, it can reject the attempt to
release (by setting a parameter in the S-RELEASE.response primitive), and the session continues as if nothing had
happened. A session is only terminated when both parties have had enough.
If you think it strange that orderly release is present in the session layer but not in the transport layer, rest
assured that you are not alone. When drafting the transport layer standard for the U.S. Government, the National
Bureau of Standards (NBS) also thought it pretty strange, and decided to add an orderly release option to the
transport layer, thus solving the problem and simultaneously making the U.S. standard different from that used by the
rest of the world. People in the standards business frequently have to choose between doing it right and doing it the
way everybody else does it. This is why there are so many standards.
Addressing is another area in which the session and transport layers differ, although only slightly. To
establish a session, one must specify the SSAP address (rather than TSAP address) to connect to. Although the
standards do not tell how SSAP addresses are to be constructed, it is likely that in practice an SSAP address will
consist of a TSAP address plus some additional identifying information.
One more way in which session data exchange differs from transport data exchange is the number of
different kinds of data. The transport layer has two logically independent data streams, regular data and expedited
data. The session layer has both of these, and two more (typed data and capability data). The other two streams relate
to features of the session layer that we have not yet covered, so we will defer our discussion of them until later in this
chapter.

7.1.3. Dialog Management

In principle, all OSI connections are full duplex, that is, PDUs can move in both directions over the same
connection simultaneously; Full-duplex communication IS shown in Fig. 7-4(a). However, there are many situations
in which the upper-layer
software is structured to expect the users to take turns (half-duplex communication). This design has nothing
to do with the limitations of some ancient terminals still in existence that cannot work in full-duplex mode, but with
designing upperlayer software in a convenient way.
As an example, consider a database management system that can be accessed from remote terminals (e.g.,
airline reservation or home banking). The most natural mode of operation is for the user to send a query to the
database system and then wait for the reply. Allowing users to send a second and a third query before the first one
has been answered needlessly complicates the system. Logically, it is desirable to operate the system in half-duplex
mode: either it is the user's turn to transmit or the database system's. Keeping track of whose turn it is to talk (and
enforcing it) is called dialog management, and is one of the services that can be provided by the session layer when
requested.
The way that dialog management is implemented is by the use of a data token.
When a session is established, half-duplex operation is one of the options that can be selected. If half-duplex
operation is chosen, the initial negotiation also determines which side gets the token first. Only the user holding the
token may transmit data; the other one must remain silent. When the token holder has finished transmitting, it passes
the token to its peer using the S-TOKEN-GIVE.request primitive, as shown in Fig. 7-4(b).
What happens if the user not holding the token wants to transmit some data? It
. can politely ask for the token using the S-TOKEN-PLEASE.request primitive. The token holder can agree, and
pass the token, or it can refuse, in which case the other user will just have to wait (or send an emergency message
using expedited data, which does not require the token). If full-duplex operation is selected when the session is
established, no token is used for data transmission.
7.1.4. Synchronization

Another service of the session layer is synchronization, whit:h is used to move the session entities back to a
known state in the event of an error or disagreement. At first glance, such a service would seem unnecessary because the
transport layer has been carefully designed to transparently recover from all communication errors and subnet crashes.
However, closer study shows that the transport layer has been designed to mask only communication errors. It cannot
r~cover from upper layer errors.
As an example of the problems that can occur, consider the teletex service that is gradually replacing telex (TWX)
for sending hard copy messages from one company to another. Subscribers to this service use a device containing an
embedded CPU, k~yboard, display, printer, modem, telephone and sometimes a disk. The user first composes a message
using the CRT and keyboard. Then the CPU calls up the company to which the message is to be sent, establishes a session,
and transfers the message. If the receiving device has no disk storage, a real possibility in the cheaper versions, incoming
messages must be printed in real time, as they are received.
As soon as each SPDU is received, it is acknowledged and text is given to the printer to print. Now suppose that a
paper or ribbon jam occurs. Even if the human operator notices the problem quickly and hits a button on the device to stop
printing, some information may be lost. Since it has already been acknowledged, the sender will no longer have a copy,
and the message transmission will fail. There is nothing that the transport layer can do about this problem. After all, it has
done its job perfectly: it moved all the bits reliably from sender to receiver. Only after handing the SPDU to the session
layer did it send back an acknowledgement. It is not the transport layer's fault that the upper layers dropped the ball.
The solution lies in the session layer. The session users can split the text up into pages and insert a
synchronization point between each page, as shown in Fig. 7-5. In case of trouble, it is possible to reset the state of the
session to a previous synchronization point and continue from there. Of course, in order to make this process, called
resynchronization, possible, the sending session user (not the session entity) must continue to hold data as long as it
might be needed.

It is important to understand what the semantics of synchronization are in the session layer. Session users can
insert synchronization points in the message
stream. Each synchronization point bears a serial number. When one user issues a primitive to request a
synchronization point, the other one gets an indication. Similarly, when one issues a primitive to l'esynchronize, the other
one gets an indication of that, too. The saving of messages and subsequent retransmission later is all handled above the
session layer. All the session layer provides is a way of conveying numbered synchronization and resynchronization
signals across the network.
The mechanism is actually slightly more complex than we have sketched so far.
Two different kinds of synchronization points exist, major and minor, each with its own primitives. The units
delimited by major synchronization points are called dialog units, and usually represent logically significant pieces of
work. When transmitting a book, for example, the chapters might be delimited by major synchronization points and the
pages by minor ones. Figure 7-6 shows a session with three major and four minor synchronization points.
7.1.5. Activity Management

Another key feature of the session layer, closely related to synchronization, is activity management. The idea
behind activity management is to let the user split
•the message stream up into logical units called activities. Each activity is completely independent of any
other activities that may have corne before it or will corne after it.
Major and minor synchronization points differ in several ways. For one thing, when resynchronizing, it is only
possible to go back as far as the most recent major synchronization point and no further. Thus in the time interval between
synchronization points 6 and 7 in Fig. 7-6, it is permitted to resynchronize back to 6, but not to l, 2, 3, 4, or 5. By erecting
a brick wall at each major synchronization point, the sender knows that data that were sent before it can be safely
discarded. Minor synchronization points do not have this property. Just before synchronization point 6 in Fig. 7-6 it is
permitted to resynchronize to l, 2, 3, 4, or 5. The choice of which type of synchronization point to use and where to use it
is up to the session users, of course.
Major synchronization points are so significant that each one inserted into the data stream is explicitly confirmed
(acknowledged). Minor synchronization points are not confirmed. On a satellite channel, where the minimum delay to
send a message and get an acknowledgement is 540 msec, this distinction can be significant.
Setting a synchronization point, either major or minor, requires possession of the relevant tokens. Two
independent tokens are available (for major and minor synchronization). They are distinct from each other and also distinct
from tht: token used to control data flow in half-duplex connections. When resynchronization occurs, all the tokens are
restored to the positions they had at the instant that the synchronization point was set.
It is up to the user to determine what an activity is. As a first example, consider a session that has been set up
for the purpose of transferring several files between two computers. Some way is needed of marking the place where
one file ends and the next one begins. Using the ASCII FS (File Separator) character is not a good idea because if the
files contain binary information, this character might appear in the data and accidentally signal end of file when that
is not intended. Using some form of character stuffing, as is done in the data link layer, is a possibility, but in the
session layer the stuffing will probably have to be done in software rather than hardware, so it will be slow.
What is really needed is some way to insert a marker into the message stream that is itself distinct from a
data message (sometimes called out of band information). One way of achieving this goal is to define each file
transfer as a separate activity, as illustrated in Fig. 7-7. In this figure, before each file transfer is started, the sender
issues an S-ACTlVITY-START.request primitive. This comes in on the other side as an S-ACTlVITY-START.indication to
mark the start of the file. Similarly, after each file transfer is completed, the S-ACTlVITY-END primitive can be used to
denote end-of-file.
It is important to emphasize here that the choice of what constitutes an activity is made by the users, not the
session layer. All the session layer does is ensure that when one of the S-ACTlVITY requests is made by one user, the
other user gets the corresponding indication. When such requests are made and how the recipient reacts to the
indications are of no interest to the session layer. The session layeris only concerned with the execution of the
primitives, not their meaning (semantiCs) or use. It is worth noting that an activity covers all traffic sent in both
directions.
As a second example of how activity management can be used, consider a home banking system in which
people can pay bills by using their personal computers to transfer money from their accounts to those of the
companies issuing the bills. The program running on the personal computer might start out by asking for the number
of the account to be debited and send that information to the bank as the first message. Then it could successively ask
for the number of the account to be credited and the amount, and send these items in messages two and three.
When the first message arrives at the bank's computer, the disk record containing the account to be debited is
located and locked to prevent any concurrent access. When the second message arrives, the record for the account to
be credited is also locked. When the third message arrives, the money is transferred and both accounts are unlocked.
Imagine what would happen if an electrical power failure blacked out the user's home just after the first
message had been sent, received at the bank, and processed. The transaction would never be completed and the
locked account would remain locked forever. To avoid situations like this, the banking transaction might be
structured as a session layer activity. After receiving the S-ACTIVITYSTART. indication, the bank's computer could
simply accumulate incoming messages until the S-ACTIVITY-END . indication signaled that there were no more. Only
then would processing and locking begin. In this way, no external failures could cause the bank's computer to get
stuck half way in a transaction.
The technique of collecting messages in an input buffer until all of them have arrived before starting to
process any of them is called quarantining. In early drafts of the session layer, quarantining was an explicit session
service. However, later, the ISO committee realized that quarantining could equally well be accomplished using
activity management, so the quarantine service was not included in the published standard.
Our third and last example of activity management makes use of a property that we have not yet mentioned:
activities can be interrupted (i.e., suspended) and later restarted without loss of information. Consider the case of
someone who has started to download a very long file from his computer at work to his personal computer at home.
Half-way through the transfer, he needs to make an urgent telephone call and needs to look up the telephone number
in his on-line telephone directory at work, preferably without ruining the file transfer.
The solution to this problem is given in Fig. 7-8. The file transfer is started as an activity. Part way through it
is possible to issue an S-ACTIVITY!lVTERRUPT.request to suspend the file transfer. Then another activity can be started
and completed, and finally the original activity can be resumed from the ;mint where it was interrupted.
Activity management is the primary way to structure a session. For this reason, it is essential that both parties
agree on what the activity structure is. A problem ;:ould arise if both of them tried to start activities simultaneously.
To prevent this event from occurring, activity management is controlled by a token (in fact the same token used for
major synchronization points). To invoke an activity service, a
user must be in possession of the activity token. This token can be passed and requested independently of the
data and synchronize-minor tokens.
Actually, the situation is somewhat more complicated than we have just sketched. It started out as we have
described it, but later on, ISO realized that problems could occur if one user started an activity while the other was
doing a minor synchronization. To prevent this situation, the rules were changed to require a user to hold both the
activity and synchronize-minor tokens, as well as the data token (if used) before initiating an activity or a
synchronization operation. This strategy eliminated the original problems, but created a new one: what happens if
one user holds the activity token and the other one holds the synchronize-minor token, and both users want both
tokens. Each sits in a loop issuing S-TOKEN-PLEASE primitives, getting nowhere. A deadlock ensues. The only
solution is for all applications to try to be very, very careful. In retrospect, a single token might have been better.
Activities are intimately related to synchronization points. When an activity is started, the synchronization
serial numbers are reset to 1 and a major synchronization point is made. It is possible to make additional
synchronization points, both major and minor, within an activity
Because the start of each activity also corresponds to a major synchronization
point, once an activity has started, it is not possible to resynchronize to a point earlier than the start6f that activity.
·In particular, it is not possible to resynchronize to a synchronization point in a previous activity.
7.1.6. Exception Reporting
Another session layer feature is a general-purpose mechanism for reporting unexpected errors. If the user runs into
trouble, for whatever reason, this trouble can be reported to the peer using a S-U-EXCEPTION-REPORT.request primitive.
Some user data may be transferred using this primitive. The user data typically will explain what happened.
As an example, suppose a programmer designs a complex special-purpose layer 7 protocol for some specific
application. During debugging of the protocol (or even after it is supposedly debugged) protocol errors may occur. These
can be reported to the peer using the session layer exception reporting mechanism.
Exception reporting does not only apply to user-detected errors. The service provider can generate an S-P-
EXCEPTlON-REPORT.indication to notify the user about internal problems within the session layer or problems reported to it
from the transport or lower layers. These reports contain a field describing the nature of the exception. It is up to the user
to decide what action to take, if any.
7.1.7. The OSI Session Service Primitives
In this section we will systematically examine all the OSI session primitives and describe the function of each one.
They are listed in Fig. 7-10. Each line in the table corresponds to between I and 4 primitives as noted. Potentially, each
primitive type has request, indication, response, and confirm versions. However, not all the combinations are valid. S-DATA, for
example, only has request and indication. Acknowledgements (i.e., response and confirm) are taken care of by lower layers.
Although there are 58 connection-oriented session service primitives they can be better understood by dividing
them into seven groups:

1 Connection establishment.
. 2 Connection release.
. 3 Data transfer.
.
4 Token management.
.
5 Synchronization.
.
6 Activity management.
.
7 Exception reporting.
. has four tokens, as shown in Fig. 7-11. The S-TOKEN-GIVE.request primitive can be used to pass one or more
tokens to the peer entity. Parameters specify which tokens are to be given. The S-TOKEN-PLEASE.request primitive can
be used to announce that the user issuing the primitive wants the specified tokens. Finally, the
'S-CONTROL-GIVE.request can be used to surrender all the tokens at once. It can only be used outside activities.
Logically, this primitive is not necessary, but it was included at the request of CCITT for compatibility with their
teletex protocol, which works in terms of control, rather than in terms of tokens.
Data token Data transfer in half-duplex mode

Release token I nitiation of orderly release


--
Synchronize-minor token Insertion of minor sync points

Major/activity token Activity or major sync operations

Fig. 7-11. The session layer tokens.


The fifth group contains the synchronization primitives. Primitives are provided for both major and minor
synchronization, as well as resynchronization. All of the primitives are confirmed. Each primitive specifies the serial
number of the synchronization point that it wants to set or go back to. These serial numbers are in the range 0 to
999,999. All synchronization primitives require possession of the relevant tokens.
The sixth group of primitives relates to activity management. Activities can be started, interrupted, resumed,
and discarded (abandoned). Like synchronization, activity management is controlled by tokens.
The seventh and last group contains the exception reporting primitives. Note that SoP-EXCEPTION, like S-P-
ABORT cannot be requested. The service provider decides when and if to issue it.
The OSI primitives are implemented by the session entity using the session protocol. We will discuss this
protocol later in this chapter.
72. REMOTE PROCEDURE CALL
The primary concern of the session layer is managing the dialog and dealing with errors (e.g., system crashes)
occurring above the transport layer. In the OSI Refelence Model, a connectionless session makes little sense.
However, there has been considerable research at universities and in industry on a radically different model for dialog
and error control based on the connectionless model. This work, which goes under the name RPC (Remote Procedure
Call), has been widely implemented in networks and (especially) distributed systems.
RPC does not fit into the OSI Reference Model especially well. It has been designed to be fast, and therefore
does not contain a multilayer structure. Logically, remote procedure call is concerned with roughly the same issues as the
session layer (although from a very different perspective), so we will examine it in this chapter. Please note, however, that
RPC can also be implemented in the application layer (although less efficiently), so one sometimes finds discussions of it
in that context.

7.2.1. The Client-Server Model

Up until now, we have tacitly assumed that the two processes communicating over a session or transport
connection are symmetric. In practice, this assumption is frequently violated. A common example is a network of diskless
personal computers or workstations, called clients, that are communicating over a network with a file server having a disk
on which all the files are stored. In this system, clients access their data by sending requests to the server, which carries out
the work and sends back the replies. Communication always takes the form of request-reply pairs, always initiated by the
clients, never by the server. This model is called the client-server model. While it is obviously possible to establish
sessions between clients and servers and then use half-duplex communication over these sessions, the high overhead
caused by multiple layers of connections is frequently unattractive for applications, such as file servers, where
performance is critical. A fully connectionless form of communication built right on top of the raw datagram facility
(especially on LANs) is often a much better choice.
Even if the performance problems can be solved by using connectionless mode, the model still has a major flaw:
the conceptual basis of all communication is I/O (input/output). Programs communicate with other programs using
commands such as X-DATA.request and X-DATA.indication, the former of which is I/O and the latter of which is an interrupt.
These are hardly the proper tools for building wellstructured applications.
The RPC school of thought approaches the client-server model from a completely different perspective. In this
view, a client sending a message to a server and getting a reply is like a program calling a procedure and getting a result. In
both cases, the caller initiates an action and waits until it is completed and the results are available. Although in the
ordinary (local) case, the procedure runs on the same machine as the· caller, and with RPC it runs on a different machine,
the caller need not be aware of this distinction.
To help hide the difference between local and remote calls even more, it is possible to embed RPC in the
programming language. Suppose, for example, that we 'provide each of the file server's clients with a (library) procedure,
read, that can be called with three parameters: an identifier telling which file to read, a buffer to read the data into, and a
count of the number of bytes to read. A call like
read(fileid, buffer, count)

is then an ordinary call to a local procedure (i.e., a procedure included in the caller's address space by the linker).
This procedure sends a message to the file server and waits for the reply. Only after the reply arrives, does read return
control to the caller.
The beauty of this scheme is that client-server communication now takes the form of procedure calls instead of
I/O commands (or worse yet, interrupts). All the details of how the network works can be hidden from the application
program by putting them in the local procedures such as read. These procedures are called stubs.
In this example, the stub procedure actually transfers data, but a stub procedure can equally well send a message
requesting the server to perform an arbitrary operation. For example, a call
delete( filename)

might cause the stub procedure, delete, to send a message to the file server asking it to destroy the specified file.
By providing appropriate stub procedures, we can have the client invoke arbitrary actions on the server in a way that is
much more natural for the applications programmer to deal with than I/O and interrupts. The ultimate goal is to make a
remote procedure call look no different than a local procedure call.

7.2.2. Implementation of Remote Procedure Call

In this section we will take a closer look at how RPC is implemented. More information can be found in the work
of Birrell and Nelson (1984). Figure 7-13 shows one way of implementing a remote procedure call system. In this figure,
the remote call takes ten steps. Step 1 consists of the client program (or procedure) calling the stub procedure linked within
its own address space. Parameters may be passed in the usual way. The client does not notice anything unusual about this
call because it is a normal, local call.
The client stub then collects the parameters and packs them into a message.
This operation is known as parameter marshalling. After the message has been constructed, it is given to the
transport layer for transmission (step 2). In a connectionless LAN system, the transport entity will probably just attach a
header to the message and put it out on the network without further ado (step 3). In a WAN, the actual transmission
may be more complicated. In many systems, step 2 is a trap to the operating system.
When the message arrives at the server, the transport entity there passes it to the server stub (step 4), which
unmarshalls the parameters. The server stub then calls the server procedure (step 5), passing the parameters in the
standard way. The server procedure has no way of telling that it is being activated remotely because its immediate
caller is a local procedure that obeys all the standard rules. Only the stubs know that something peculiar is going on.
After it has completed its work, the server procedure returns (step 6), the same way as any other procedure
returns when it is finished. It may also return a result to its caller. The server stub then marshalls the result into a
message and hands it off at the transport interface (step 7), possibly by making a system call, just as in step 2. After
the reply gets back to the client machine (step 8), it is handed to the client stub (step 9). Finally, the client stub
returns to its caller, the client procedure. Any value returned by the server in step 6 is given to the client in step 10.
The purpose of the whole mechanism of Fig. 7-13 is to give the client procedure the illusion that it is making
a direct calion the distant server procedure. To the extent that the illusion succeeds and the client cannot tell that the
server is remote, the mechanism is said to be transparent. However, a closer inspection reveals some difficulties in
achieving full transparency.
The principal problem occurs with the parameter passing. Passing integers, floating point numbers, and
character strings by value is easy. The client stub just puts them in the message. At worst, a conversion to some
network standard format might be needed (such conversions are part of the presentation layer, and will be discussed
at length in the next chapter). Passing structures, records, or arrays of these types is equally straightforward.
The trouble comes when the language allows parameters to be passed by reference, rather than by value. For
a local call, a pointer (the address of the parameter) is normally passed to the called procedure. The called procedure
knows that it is
dealing with (! reference parameter, so it can follow the pointer to access the parameter.
This strategy fails completely for a remote call. When the compiler produces code for the server, it knows
nothing about RPC, and generates the usual instruc-
, tions for following pointers. Of course the object being pointed to is not even on the server's machine, and
even if it were, it would not have the same address there as it had on the client's machine. As a result, when the server
tries to use a reference parameter, it gets the wrong value and the computation fails.
One possible solution is to replace the call-by-reference parameter mechanism by call-by-copy/restore. With
copy/restore, the client stub locates the item being pointed to, and passes it to the server stub. The server stub puts it
in memory somewhere. and passes a pointer to it to the server procedure. The server is then able to access the item in
the usual way. When the server procedure returns control to the stub, the stub sends the (possibly modified) data item
back to the client stub, which uses it to overwrite the original reference parameter.
Although the copy/restore mechanism frequently works, it can fail in certain pathological situations.
Consider, for example, the program of Fig. 7-14. When this program runs locally, both of the parameters in the call to
doubleincr are pointers to a, which gets incremented twice. The number 2 is printed.
Now let us see what happens if doubleincr is called as a remote procedure using copy/restore. The client stub
processes each parameter separately, so it sends two copies of a· to the server SI ub The server procedure increments
each copy once, and both are passed back to the client stub, which then restores them sequentially. First a is restored
to I and then it is restored to I again. Thus the final value is 1 instead of the correct answer, 2.
Pointers give problems similar to reference parameters. They are especially troublesome if they point into the
middle of conLplex lists or graphs or data structures involving variant records. Procedure or function parameters also
are difficult to handle, although it may be possible for the server stub to replace them by procedures local to the
server's machine that invoke the called procedures back on the client's machine using reverse RPC.
Many RPC systems finesse the whole problem by prohibiting the use of reference parameters, pointers, and
procedure or function parameters on remote calls. Such a decision makes the implementation easier, but breaks down
the transparency because the rules for local and remote calls are then different.
Let us now turn from parameter passing to another implementation issue: How does the client stub know
who to call? In traditional connection-oriented networks, sessions are established between SSAPs, each of which has
a fixed "telephone number." For RPC a simpler, yet more dynamic, scheme is needed.
Birrell and Nelson (1984) have described a scheme involving not only clients and servers, but also a
specialized kind of data base system. In their method, illustrated in Fig. 7-15, when a server is booted, it registers
with the data base system by sending a message containing its name (as an ASCII string), its network address (e.g.,
an NSAP, TSAP, or SSAP), and a unique identifier (e.g., a random 32-bit integer). This registration is done by having
the server call a procedure export, which is handled by the stub (steps 1 and 2).

Fig. 7-15. Client-server binding is done via a data base.

Later, when the client makes its first call (step 3) and its stub is faced with the problem of locating the server,
the stub sends its name, which is also the server'L name, in ASCII, to the data base system (step 4). The data base
system then returns the server's network address and the unique identifier (step 5). This process is called binding.
From this point on, the stub knows how to locate the server, so binding is not required on subsequent calls.
The unique 32-bit identifier is included in each RPC call. It is used by the transport entity on the server's
machine to tell which of the potentially many server stubs to give the incoming message to. It also has another role.
If the server crashes and reboots, it re-registers with the data base system using a new unique number. Attempts by
clients to communicate with it using the old unique identifier will fail, making them aware of the crash and forcing
them to rebind.
Another key implementation issue is the protocol used. In the simplest case, the RPC protocol can consist of
two messages: a request and a reply. Both the request and the reply contain the unique number identifying the server,
a transaction identifier, and the parameters. When sending a request, the client stub (in some systems) may set a
timer. If the timer goes off before the reply comes back, the stub can query the server to see if the request arrived. If
not, it can retransmit it. The purpose of the transaction identifier is to allow the server to recognize and reject
duplicate requests. Recognizing duplicate requests is only possible if the server keeps track of the most recent
transaction identifier from each client.
A final implementation issue is exception handling. Unlike local procedure calls, where nothing
can go wrong, many things can go wrong with RPC, for example, the server could be down. If the
programming language allows it, the occurrence of an RPC error should not give control back to the caller,
but should raise an exception to be handled by an exception handler. The design of the exception handling
mechanism is language dependent, but a method is clearly needed to distinguish unsuccessful calls from
successful ones.

You might also like