Building a Simple RPC Client and Server: A Step-by-Step Guide

Author

Pavel Yosifovich
25+ years as Software developer, trainer, consultant, author, and speaker. Co-author of “Windows Internals”. Author of “Windows Kernel Programming”, “Windows 10 System Programming, as well as System and kernel programming courses and “Windows Internals” series.

Note: This blog post is designed to complement the accompanying video embedded at the top of the page. The video provides an in-depth, visual demonstration of the concepts and code discussed here, making it an invaluable resource for learners.

Remote Procedure Calls (RPC) are a fundamental mechanism in distributed computing, allowing functions to execute seamlessly across different systems or processes as if they were local. This post walks you through creating a basic RPC server and client using Microsoft’s RPC framework, focusing on clarity and simplicity.


What Is RPC?

RPC (Remote Procedure Call) is a protocol that enables a program to execute a procedure on a remote system with ease, as if it were a local call. Microsoft’s implementation of RPC supports multiple communication mechanisms, such as:

  • ALPC (Advanced Local Procedure Calls): Used for communication within the same machine.
  • TCP: Enables network-based communication.
  • Named Pipes: Another popular option for interprocess communication.

While RPC powers many underlying technologies (e.g., COM), this guide focuses on core RPC concepts without the additional complexity of object-based frameworks.


Windows master developer badge 1

$1,478

$1182 or $120 X 10 payments

Windows Master Developer

Takes you from a “generic” C programmer to a master Windows programmer in user mode and kernel mode.

Step 1: Define the Interface

The foundation of an RPC setup lies in the interface definition. Interfaces define the functions available for remote execution and their parameters. In this example, we use an Interface Definition Language (IDL) file to declare a simple function to add two numbers:

interface Calculator
{
    int Add([in] int a, [in] int b);
}

IDL ensures precise parameter handling, crucial for remoting scenarios where data needs to be transmitted between processes or systems.


Step 2: Generate Necessary Files

The IDL file is processed by the MIDL compiler to generate several files:

  • Header File (.h): Contains the interface declaration for use in both client and server.
  • Stub Files (.c): Contains code to marshal and unmarshal data for RPC communication.

These files bridge the gap between the client and server, facilitating seamless communication.


Step 3: Build the RPC Server

The server needs to:

  1. Register the Interface: Link the implementation of the interface with the RPC runtime.
  2. Expose an Endpoint: Define a communication channel (e.g., ALPC, TCP).
  3. Implement the Function: Provide the actual logic for the Add function.

Here’s a simplified implementation of the Add function:

int Add(handle_t hBinding, int a, int b) {
    printf("Add invoked with: %d, %d\n", a, b);
    return a + b;
}

Step 4: Build the RPC Client

The client establishes a connection with the server and invokes the remote function:

  1. Compose a Binding String: Define how to connect to the server, specifying protocol and endpoint.
  2. Create a Binding Handle: Use the binding string to establish a connection.
  3. Call the Remote Function: Invoke the Add function via the binding handle.

Example client code:

RPC_BINDING_HANDLE hBinding;
// Setup the binding here...
int result = Add(hBinding, 5, 10);
printf("Result: %d\n", result);

Step 5: Test the Setup

Run the server first to start listening for connections. Then, run the client to test the interaction. Use debugging tools like Process Explorer to inspect ALPC ports and monitor messages exchanged between client and server.


Practical Applications

This simple example demonstrates the basics of RPC. In real-world scenarios, RPC is used for:

  • Distributed systems communication.
  • Enabling client-server models in applications.
  • Simplifying interprocess communication (IPC) in complex software architectures.

Conclusion

Creating an RPC client and server is an essential skill for developers working with distributed systems or advanced IPC mechanisms. By following the steps above, you can build a foundational understanding of RPC while experimenting with practical examples.

Explore the accompanying video for a detailed walkthrough of the code and concepts, and keep experimenting to uncover the full potential of RPC in your projects!

Gain Insider Knowledge

Subscribe to updates from the TrainSec trainers

For more insights into Windows internals and advanced programming concepts, keep exploring TrainSec’s Knowledge Library. Stay tuned for more deep dives into topics that empower your technical growth!

blue depth

About the author

Pavel Yosifovich
25+ years as Software developer, trainer, consultant, author, and speaker. Co-author of “Windows Internals”. Author of “Windows Kernel Programming”, “Windows 10 System Programming, as well as System and kernel programming courses and “Windows Internals” series.