Skip to main content
In this article, we explain how to build a simple networked file transfer tool—a basic client-server application using Rust. The client reads a file in chunks and sends it to the server over a TCP connection. The server reassembles these chunks, writes them to disk, and acknowledges the successful file transfer.
The image is a flowchart illustrating the interaction between a user, client, and server, detailing steps like providing a file path, connecting to the server, and sending file chunks.

Application Features

  • TCP Communication: Uses TCP sockets to establish reliable client-server communication.
  • File Transfer: Transfers a single file from the client to the server.
  • File Path Input: The client prompts the user to input the absolute file path of the file to send.
  • Error Handling: Implements basic error handling during connection setup and file transfer.
The image outlines four features: TCP Communication, File Transfer, File Path Input, and Error Handling, each with a brief description.

Core Components

Server

The server component consists of a TCP listener that binds to a specified port, accepts client connections, reads file chunks, and writes them to disk. Once the entire file is received, the server sends an acknowledgment back to the client.
The image outlines the core components of a server, including a TCP listener, accepting connections, and file saving. Each component is briefly described in terms of its function.

Client

The client takes user input for the file path, connects to the server via TCP, reads the file in manageable chunks, and sends these chunks to the server. It includes error handling and waits for the server’s acknowledgment before closing the connection.
The image outlines the core components of a client system, detailing user input, TCP connection, and file reading processes.

Client Execution Flow

  1. Prompt the user for the absolute file path.
  2. Establish a TCP connection to the server.
  3. Open the file and read it in fixed-size chunks (e.g., 1024 bytes).
  4. Send each file chunk to the server.
  5. Wait for the server’s acknowledgment after transmitting all chunks.
  6. Close the TCP connection.
The image is a flowchart titled "Client Execution Flow," detailing steps for a client application to transfer a file, including prompting for a file path, connecting to a server, reading and sending file chunks, and acknowledging completion.

Server Execution Flow

  1. The server listens on a predefined TCP port.
  2. It accepts incoming connections from clients.
  3. It reads the file chunks sent by the client and writes them to disk.
  4. After receiving the complete file, the server sends an acknowledgment back to the client.
  5. The connection is then closed.
The image illustrates a server execution flow, detailing steps such as listening for connections, accepting client connections, receiving files in chunks, and sending acknowledgments.

File Transfer Details

The file transfer is optimized for large files by reading and sending data in chunks. If a file with the same name already exists on the server, it will be overwritten.
The image explains file transfer details, highlighting chunk size for efficient file handling and file overwrite behavior when a file with the same name exists.

Libraries and Tools

This project leverages several Rust standard libraries and tools:
  • std::net::TcpListener and TcpStream: For establishing and managing TCP connections.
  • std::fs::File: For file operations such as reading and writing.
  • std::io::: For handling data input/output.
  • std::io::stdin: For managing standard input.
The image lists libraries and tools related to networking and file operations, alongside an illustration of connected devices.

Code Walkthrough

Below is a step-by-step walkthrough of the server and client code for our file transfer application.

Project Setup

  1. Create a new Rust project by executing the following command in your project directory:
  2. Inside the src directory, create a new folder named bin and add two files: client.rs and server.rs. This separation keeps the server and client logic distinct.

Server Code

The following code demonstrates the server functionality, including error handling and proper chunked file writing:

Client Code

The client code prompts the user for the file path, reads the file in chunks, sends each chunk to the server, and waits for an acknowledgment upon completion.

Running the Application

  1. Build the Project Run the following command to build the project:
  2. Run the Server Open a terminal and run the server with:
    You should see output like:
  3. Run the Client Open another terminal and run the client with:
    When prompted, enter the absolute file path of the file to send. An example interaction is shown below:
On the server terminal, you will see logs detailing each received chunk, the end-of-file notification, and the acknowledgment status.

Summary

In this article, we built a networked file transfer application using Rust and TCP sockets. The client reads a file in chunks and sends it to the server, which writes the chunks to disk and sends back an acknowledgment upon successful completion.
This basic application can be extended with features such as file compression, encryption, or support for transferring multiple files concurrently.
The image is a summary slide outlining the creation of a network file transfer app using TCP sockets, detailing the process of file transfer in chunks, and learning file handling and networking with Rust.
We hope you enjoyed building this project and learning about networked file transfers with Rust!

Watch Video