
Remote Procedure Call (RPC)
RPC is a communication mechanism that allows a program to call a procedure (function) on a remote machine as if it were local.
It hides the complexity of network communication by providing a higher-level abstraction compared to raw sockets.
Data serialization formats (e.g., ProtoBuf, JSON, XML) are often used to ensure consistency across different systems and languages.
<strong>Its purpose is to allow a program to execute subroutine in another address space. Makes distributed system appear like a centralized system to the user, to avoid low-level bugs. </strong>
<br><br> Primarily runs at the Session Layer (Layer 5) of the OSI Model
<h2>RPC Limitations</h2>
<ul>
<li>Pass by reference not possible (since remote systems don’t share memory). Must use pass by value.</li>
<li>Latency and network failures prevent full transparency.</li>
</ul>
<h2> Stubs </h2>
<br><br> Remote procedures are locally represented by stub -- the client stub and the server stub. The client stub is a local proxy for a remote object (A proxy function on the client side that looks like the actual procedure the client wants to call) suc that the client can call the client stub like it would call a local function.
<br> The client stub's job is to:
<ul>
<li>Marshal (package/serialize) the procedure name, arguments, and metadata into a message.</li>
<li>Send the message across the network to the server.</li>
<li>Wait for a response, then unmarshal (deserialize) the return value and hand it back to the client.</li>
To the client program, it feels exactly like a normal function call - the complexity of the networking is hidden.
</ul>
<br>

Threads and Execution
- Single-threaded process → has a single flow of control.
- Kernel threads → managed by the operating system, can run independently, and each gets its own Process Control Block (PCB).
How RPC Works (Client/Server Roles)
- The client calls a local stub function (proxy for the remote procedure).
- The stub marshalls (packs) parameters into a byte stream.
- The stub sends the byte stream over the network to the server stub.
- The server stub unmarshalls the request, reconstructs parameters, and invokes the actual server procedure.
- The procedure executes and returns a result.
- The server stub marshalls the result and sends it back.
- The client stub unmarshalls the return value and gives it to the client program.
From the client’s perspective, it looks like a local function call.
Marshalling (Serialization)
Converts complex data structures (objects, arrays, etc.) into a format suitable for network transfer (e.g., byte sequences).
Handles:
- Different programming languages (C++, Java, Ada, etc.)
- Data type representation differences (e.g., 32-bit vs 64-bit integers).
- Endianness (big-endian vs little-endian).
Both client and server must agree on an encoding scheme.
Marshalling is the act of client and server stubs building an intermediate representation to communicate even when using different languages, data type reps, and endianness.
RPC Fault Semantics
Because RPC occurs over unreliable networks, several failure handling semantics exist:
- At least once: Retries until acknowledgement is received. Safe for idempotent operations (e.g.,
SET x=5always has the same result). - At most once: Each request has a unique ID, preventing duplicate executions. Used for non-idempotent operations (e.g., billing a credit card).
- Exactly once: Ideal but hard to achieve. Requires tracking both requests and responses.
Common Faults in RPC
- Lost messages (due to unreliable transport).
- Client crash before receiving response.
- Server crash while executing procedure.
- Synchronization issues when multiple clients make concurrent requests.
- Lost replies (server executes but response is dropped).
RPC Client–Server Flow
9. Stub sends reply
RPC Client Stub Example
A simplified C/C++ example showing how a client stub sets up a server address, create a UDP socket, and serialize a key-value request before sending.
// Step 1: Start client stub
ClientStub c = ClientStub();
c.setServerAddress("10.0.0.2", 4); // set server address (done internally by stub)
// Step 2: Create a UDP socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
// handle failure
}
// Step 3: Message serialization
KVPut request; // create a key-value PUT request object
request.key = "x";
request.value = 42;
// Stub marshalls the object, sends it to the server.

















