Skip to main content
This guide will walk you through creating a simple RDP client that connects to a server, captures graphics updates, and saves them as an image.

Prerequisites

Ensure you have:
  • Rust 1.88.0 or later installed
  • An RDP server to connect to (Windows machine, RDP server, etc.)
  • Basic familiarity with Rust and async programming

Project Setup

1

Create a new Rust project

2

Add dependencies

Edit Cargo.toml to include IronRDP and required dependencies:
3

Set up logging (optional but recommended)

Run with logging:

Building a Simple Screenshot Client

Step 1: Configure the Connection

Create a configuration for connecting to the RDP server:
The configuration includes many fields for fine-grained control. Most can use sensible defaults as shown above.

Step 2: Establish the Connection

Connect to the RDP server using blocking I/O:

Step 3: TLS Upgrade Helper

Implement TLS upgrade with certificate verification disabled (for testing):
This example disables certificate verification for simplicity. In production, always validate server certificates properly.

Step 4: Process the Active Stage

Handle the active session and capture graphics updates:

Step 5: Complete Example

Running the Example

1

Build the project

2

Run with your RDP server details

Or with logging:
3

Check the output

You should see output.png in your project directory containing a screenshot of the remote desktop.

Key Concepts Explained

Connection Lifecycle

1

Initial Connection

connect_begin() starts the RDP handshake over TCP
2

TLS Upgrade

The connection is upgraded to TLS for security
3

Authentication

connect_finalize() completes authentication (CredSSP, NLA, etc.)
4

Active Stage

The session enters active mode, processing graphics updates and user input

Understanding ActiveStage

The ActiveStage is the heart of an RDP session:
Key outputs:
  • ActiveStageOutput::ResponseFrame - Data to send back to the server
  • ActiveStageOutput::GraphicsUpdate - Screen content changed
  • ActiveStageOutput::Terminate - Connection closed

Image Decoding

DecodedImage manages the remote desktop framebuffer:

Building an Async Client

For production use, prefer async I/O with Tokio:
Refer to the full ironrdp-client implementation in the repository for a complete async example with GUI support.

Common Issues

Symptom: TcpStream::connect hangs or times outSolutions:
  • Verify the server is reachable (ping the host)
  • Check firewall rules (port 3389 must be open)
  • Ensure RDP is enabled on the target machine
Symptom: Error during connect_finalizeSolutions:
  • Verify username and password are correct
  • Check domain name (use None for local accounts)
  • Ensure CredSSP is enabled on the server
Symptom: Screenshot is saved but appears blankSolutions:
  • Increase the read timeout (some servers send updates slowly)
  • Add a delay before saving the image to capture more updates
  • Check logs for errors during graphics decoding
Symptom: Error during tls_upgradeSolutions:
  • Ensure the server supports TLS 1.2 or later
  • Try with enable_tls: false for testing (not recommended for production)
  • Check server certificate validity

Next Steps

Now that you’ve built a basic client, explore:

Building Servers

Create custom RDP servers with IronRDP

Virtual Channels

Implement clipboard, audio, and custom channels

Examples

Study the full screenshot and server examples

API Documentation

Deep dive into the complete API reference

Real-World Examples

The IronRDP repository includes production-ready examples:

Screenshot Example

Located at crates/ironrdp/examples/screenshot.rs - a complete blocking client in ~500 lines:

Server Example

Located at crates/ironrdp/examples/server.rs - a minimal RDP server:
Study these examples for production patterns, error handling, and best practices.