See the assignment turn-in page (last modified on 25 February 2003) for instructions on turning in your assignment.
A single sRPC server implements a single service, which consists of one or
more calls. Clients of a particular sRPC server can make any of the calls
supported by the server. For example, an sRPC server may act as an Accordion
server, supporting the calls play()
, deal()
, tableau()
, and quit()
.
An sRPC service call is similar to a normal subroutine or method call, except that an sRPC service call is more limited in the types of parameters it can use. An sRPC service-call parameter can be an integer, a string, or an array. An integer is a signed, 32-bit value. An sRPC string is a sequence of zero or more seven-bit ASCII characters; an sRPC string is not zero terminated. An sRPC array is a sequence of zero or more values of the array's base type. sRPC arrays are dynamic; they have no fixed maximum size. sRPC Arrays are also recursive; an array's base type may also be an array.
In left to right order, the components of the system are:
Although the diagram shows a single client, an sRPC server can handle multiple clients.
srpc-gen
interface-code generator.
The sRPC runtime system is responsible for implementing all sRPC functions, including data marshaling, data transmission, and sRPC system-call semantics.
The sRPC runtime system is generic with respect to the services it supports;
the same runtime system works with all possible services defined in sRPC. The
srpc-gen
interface-code generator is responsible for
creating the code that bridges the gap between the specific requirements of a
particular service and the generic facilities of the sRPC runtime system.
srpc-gen
interface generator accepts as input
a service-description file and produces as output several interface files that
let implementors access and provide services via sRPC.
A service-description file is a text file with a simple format: a service name
spec followed by one or more service-call specs. A service-name spec is a
single line starting with the text service
followed by an identifier
giving the name of the service:
service
ident
For example, the service-description file for the Accordion service might start with
service Accordion
Following the service-name spec is one or more service-call specs. A
service-call spec consists of a call-name spec followed by zero or more
call-parameter specs. A call-name spec is a single line starting with the
text call
followed by an identifier giving the name of the call:
call
ident
Each call identifier must be unique among all call identifiers in the same specification file.
Each call-parameter spec is a single line of text consisting of a direction, a type spec, and an identifier:
The direction dir is either in
or out
and indicates if the
parameter is an input (in
) or output (out
) parameter. type-spec
indicates the parameter's type; type-spec can be one of int
for an
integer, string
for a string, or array of
type-spec for an array
containing values of the given type. ident
is the parameter's name; the
identifier must be unique among all parameter names in the same service-call
spec.
For example, this service-call spec
call tableau in array of array of int piles in string state out int difference out string error
describes the Accordion service's tableau call.
call setup in string hostname in int port_number out string emsg
The sRCP server is located at hostname:port_number
. This must be the
first service call made by a client. If emsg
is emtpy after a call to
establish()
, no error occurred during the call; otherwise, emsg
contains an error description.
call query out string spec out string emsg
After the call to query()
, spec
contains the server's
service-description file and emsg
contains an error indicator as
described above.
call shutdown out string emsg
emsg
contains an error indicator as described above.
Once shutdown()
is called for a particular endpoint, any other service calls
to that endpoint are invalid.
A call to shutdown()
effects only the associated endpoint; any other
endpoints to the same sRPC server, and any other endpoints to other sRPC
servers, remain unchanged.
The server-side generic service calls allow a server to
call initialize out string emsg
emsg
contains an error indicator as described above.
initialize()
is called once by the sRPC runtime code at the start of
execution to initialize the implementor-supplied server code.
call shutdown out string emsg
emsg
contains an error indicator as described above.
shutdown()
is called once by the sRPC runtime coded at the end of server
execution.
Notice that the server interface does not include the query()
generic sRPC service call.
The specifics of binding sRPC depend on the host language. This section describes an sRPC binding to C++ as the host language; the bindings for other host languages will be similar.
The sRPC types are bound to the analogous types in C++:
sRPC type | Bound C++ type |
---|---|
int | int |
string | std::string |
array of T | std::vector< T> |
Each service call is bound to a prototype of the form
void
call-name(
input-parameters,
output-parameters
)
The left-to-right order of the input parameters matches the top-to-bottom order of the in-parameter specs in the service-spec; similarly for the output parameters. An input-parameter spec
in
type-spec ident
is bound to the formal parameter
const
bound-type-spec &
ident
or to
the choice is up to the sRPC implementor. An output-parameter spec
out
type-spec ident
is bound to the formal parameter
&
ident
As an example, the tableau service-call spec
call tableau in array of array of int piles in string state out int difference out string error
is bound to the prototype
void tableau( const std::vector<std::vector<int> > & piles, const std::string & state, int & difference, std::string & error )
The client-side generic sRPC service calls have the bindings
service-name( const std::string & hostname, short port_number, std::string & emsg ) void query( std::string & spec, std::string & emsg ) void shutdown( std::string & emsg )
The setup generic sRPC service call becomes the class's
constructor, but the shutdown generic sRPC service call does
not become the class's destructor (although the destructor may call
shutdown()
if it needs to).
On the server side, the service-call specs and server-specific generic sRPC service calls are bound to procedures in a namespace with the same name as the service.
srpc-gen
creates four C++ source files from a service-spec file:
The client.h
file contains the declarations of the client-side interface
routines defined in the client.cc
file. Any implementer-supplied
client-side code that make service calls needs to include the clients.h
file.
The client.cc
file contains the definitions of the client-side interface
routines for the service. The implementer compiles and links this file with
the client-side code.
The server.h
file contains the declarations of the server-side interface
routines called in the server.cc
file. The server-side code implementing
service calls needs to include the server.h
file.
The server.cc
file lets the sRPC server-side runtime system call-out to
the implementor-supplied code for the service. The implementer compiles and
links this file with the server-side code.
srpc-gen
.
service Accordion
Then would follow a sequence of service calls describing the interface to the accordion server:
call play out string emsg out string state
The client calls play()
to request a game from the accordion server.
play()
accepts no input parameters and returns two strings. The first
string is an error indication; the second string represents the state of the
game.
call deal in string state out string emsg out int card out string state
The client calls deal()
to receive another card from the hand.
deal()
accepts a single parameter, which is the most recently returned
state string; the return parameters are an error message, the card dealt
(assuming no error) and the updated state.
call tableau in array of array of int piles in string state out string emsg out int difference
The client calls tableau()
at the end of the game to compare it's game
against the server's game. The server returns an error indication and the
difference between the number of piles in the two games.
call quit in string state out string emsg
The client calls quit()
to end the game prematurely.
Assuming this service-description file is named accordion.srpc
and that
srpc-gen
produces C++ code, running accordion.srpc
through
srpc-gen
produces the four files accordion-client.h
,
accordion-client.cc
, accordion-server.h
, and
accordion-server.cc
.
srpc-gen
. However,
your implementation of srpc-gen
need not be written in the host langauge.
For example, you may chose C++ as the host language, but write srpc-gen
in
perl.
Your implementation of the sRPC runtime system will most likely be written in the host langauge, but that isn't an absolute requirement, although it's the easiest approach to take. For example, If you choose Java as your host language, you can write the sRPC runtime system in either Java or C++; if you use C++ you'd hook up to it through the Java Native Interface.
This page last modified on 29 March 2003.