如何使用Rust构建客户端服务器应用程序
网络应用是建立在互联网之上的服务,允许计算机轻松可靠地分享和交换数据。在这种情况下,网络服务将被称为客户端-服务器模式。两者之间建立通信以交换数据。客户端会要求提供数据,而提供这些数据的计算机被称为服务器。
在本教程中,我们将讨论客户-服务器模型的概念,因为我们使用Rust来实现整个场景。
设置Rust
Rust是一种非常低级/系统级的编程语言,就像C++或C语言一样。它注重安全、速度和并发性,确保你的设计能够让你创建高性能的程序。要开始使用Rust,你需要得到一个Rust C,也就是Rust编译器。
如果你使用的是Visual Studio 2013或更早的版本,那么你必须安装微软C++构建工具。在安装Visual C++构建工具时,请确保包含Windows 10 SDK和英文语言包组件。
另外,你可以安装一个新版本的Visual Studio,在安装过程中,选择 "C++工具"。

等待安装完成。然后继续下载Rust C,并将其安装在你的电脑上。检查Rust文档,选择适合你使用的环境的Rust安装。
这将与Rust cargo一起安装。Cargo是一个Rust软件包管理器,允许你访问远程Rust软件包。Cargo与Node.js的NPM、PHP的composer或PyPI的Python密切相关。
一旦Rust被安装,你可以运行以下内容来验证Rust开发环境的工具链是否被正确安装。
- 要检查已安装的Rust版本管理器运行。
rustup --version
- 要检查是否安装了Rust编译器,请运行。
rustc --version
- 要检查是否安装了Rust Cargo软件包管理器,请运行。
cargo --version

让我们看看如何建立一个基本的Rust项目。为了创建一个Rust项目,你使用cargo 来初始化你的应用程序。
要用cargo 来初始化你的项目,请到你的项目文件夹中运行cargo init 。
你也可以使用cargo new my_app 。这将在一个名为my_app 的文件夹中创建一个新项目。
一个Rust应用程序结构将在上述任何一种方法中被创建。这有一个Cargo.toml 文件,其中有你的基本应用配置和你要安装的Rust包/依赖。这看起来类似于Node.js的package.json 文件。它还创建了一个src 文件夹,你的Rust代码就放在这里。这个文件夹有一个main.rs ,里面有一个基本的RustHello, world! 应用程序。
为了测试这个,你可以在你初始化Rust项目的文件夹里面运行cargo run 。这个命令将为你编译、运行应用程序并将结果打印在你的终端上。

Rust模块
我们需要几个Rust模块来设置这个服务器和客户端。这些模块包括。
time::Duration- 这将帮助我们设置一个服务器需要的连接超时时间。io- 由于我们要在服务器和客户端之间发送数据,我们需要使用读写特性来访问输入和输出。net- 服务器和客户端需要进行通信。因此,我们需要网络功能,使用 ,以便本地服务器可以接受来自客户端的连接,对其进行读写。我们还需要 ,这样服务器就可以监听进入的连接,并将其绑定到服务器的套接字地址上。TcpStreamTcpListenerthread- 对于添加本地Rust线程。
用Rust创建一个服务器
创建一个项目文件夹并将其命名为client_server_app 。要开始设置Rust服务器,请初始化一个Rust项目。要做到这一点,运行cargo new server 。这将创建一个带有Rust程序配置的server 文件夹。让我们开始为Rust服务器编写一些Rust代码。前往server'ssrc 文件夹,开始编写你的main.rs 文件。
第一步:添加Rust包
将这些模块添加到你的main.rs 文件中,如下图所示。
use std::io;
use std::time;
use std ::net::{TcpListener,TcpStream};
use std::io::{Read,Write};
use std::thread;
第二步:处理发送者的信息
在设置服务器之前,服务器需要处理客户的消息。服务器必须首先访问这些消息,然后决定要执行什么操作。
// Handle access stream
//create a struct to hold the stream’s state
// Perform I/O operations
fn handle_sender(mut stream: TcpStream) -> io::Result<()>{
// Handle multiple access stream
let mut buf = [0;512];
for _ in 0..1000{
// let the receiver get a message from a sender
let bytes_read = stream.read(&mut buf)?;
// sender stream in a mutable variable
if bytes_read == 0{
return Ok(());
}
stream.write(&buf[..bytes_read])?;
// Print acceptance message
//read, print the message sent
println!("from the sender:{}",String::from_utf8_lossy(&buf));
// And you can sleep this connection with the connected sender
thread::sleep(time::Duration::from_secs(1));
}
// success value
Ok(())
}
首先,服务器将访问流/客户端消息,并在流的状态中保存它们。服务器将接受任何大小在0到512位范围内的消息。这些消息是可变的,可以由不同的客户端发送。这将允许多个客户端同时连接到该服务器。TcpStream 将允许接受新的客户端与该服务器的连接。如果连接是有效的,Ok(()) 将被执行,以验证这个连接到流地址是否真的成功。
一旦这些连接建立起来,服务器将向我们设定的缓冲区读取消息。这将把我们收到的消息,把这个缓冲区里面所有不是空白的字符作为一个String 。然后,为了完成读写操作,服务器将把这个String 转换为一个实际的utf8 字符串,然后把这个消息打印到服务器的终端。
服务器将不断循环连接的客户端。这可能会产生永久性的开销。因此,我们需要设置一个time::Duration ,允许服务器在循环发送消息时sleep 一下。
第三步:设置实际的服务器
为了使这个连接正常工作,我们需要设置localhost,并在其中设置一个端口。在这种情况下,我们将使用端口为7878 的localhost。
fn main() -> io::Result<()>{
// Enable port 7878 binding
let receiver_listener = TcpListener::bind("127.0.0.1:7878").expect("Failed and bind with the sender");
// Getting a handle of the underlying thread.
let mut thread_vec: Vec<thread::JoinHandle<()>> = Vec::new();
// listen to incoming connections messages and bind them to a sever socket address.
for stream in receiver_listener.incoming() {
let stream = stream.expect("failed");
// let the receiver connect with the sender
let handle = thread::spawn(move || {
//receiver failed to read from the stream
handle_sender(stream).unwrap_or_else(|error| eprintln!("{:?}",error))
});
// Push messages in the order they are sent
thread_vec.push(handle);
}
for handle in thread_vec {
// return each single value Output contained in the heap
handle.join().unwrap();
}
// success value
Ok(())
}
在这里,我们使用TcpListener 来实例化我们的服务器。这样,服务器可以监听新的连接,并将它们分配给一个服务器套接字地址。如果它不能与新的连接进行绑定,那么我们将返回一个错误信息。
一旦连接成功,我们要基本设定当我们的服务器收到消息时应该发生什么。我们将收集所有传入的消息到我们的流,并将它们绑定到一个服务器套接字地址。然后我们把这些消息按照发送的顺序放入一个堆中。然后,服务器将从设定的堆栈中读写每条消息。
现在你可以运行服务器并测试它是否工作。导航到server 目录并运行cargo run 。

用Rust创建一个客户端
现在让我们创建一个客户端,向服务器发送一些消息。要开始设置一个Rust客户端,请初始化一个Rust项目。要做到这一点,请导航到client_server_app 文件夹并运行cargo new client 。这将创建一个包含Rust应用程序设置的client 文件夹。让我们开始为Rust客户端编写一些Rust代码。转到client'ssrc 文件夹,开始处理你的main.rs 文件。
第一步:添加Rust客户端包
将这些模块添加到你的main.rs 文件中,如下图所示。
use std::str;
use std::net::TcpStream;
use std::io::{self,prelude::*,BufReader,Write};
第二步:设置Rust客户端
客户端需要有写消息的权限,并将其发送到服务器上。因此,我们需要一个本地主机和一个端口号,以便能够与服务器通信。
fn main() -> io::Result<( )>{
// connect
// Struct used to start requests to the server.
// Check TcpStream Connection to the server
let mut stream = TcpStream::connect("127.0.0.1:7878")?;
for _ in 0..1000 {
// Allow sender to enter message input
let mut input = String::new();
// First access the input message and read it
io::stdin().read_line(&mut input).expect("Failed to read");
// Write the message so that the receiver can access it
stream.write(input.as_bytes()).expect("failed to write");
// Add buffering so that the receiver can read messages from the stream
let mut reader =BufReader::new(&stream);
// Check if this input message values are u8
let mut buffer: Vec<u8> = Vec::new();
// Read input information
reader.read_until(b'\n',&mut buffer)?;
println!("read from server:{}",str::from_utf8(&buffer).unwrap());
println!("");
}
Ok(())
}
首先,我们将用TcpStream 创建一个可变的客户端,然后将其连接到一个带有端口号的本地主机IP上。在这里,我们可以有不同的客户端连接到同一个服务器。因此,我们需要创建一个可变的TcpStream ,以允许不同的localhost IP地址连接到服务器。
一旦客户端连接到服务器,它需要允许发送者输入一个可变的信息输入的权限。服务器现在应该打印这个消息。这些消息被读成一个字符串,然后被转换为一个utf8 缓冲区。
现在你只需要添加缓冲区,以便服务器能够从客户端流中读取消息。
让我们来测试一下。打开一个新的终端,使用cargo run 运行客户端。

确保你的服务器仍然在另一个终端上运行。到客户终端,开始输入一些信息,然后点击回车键发送。

走到服务器终端,你可以看到服务器收到了你发送的确切信息。

结论
当你连接到网络时,你的计算机向服务器发送数据。然后服务器检查这些数据,以确保它是有效的。如果数据是无效的,就会出现错误。在本教程中,我们建立了一个方便的应用程序,允许服务器和客户使用Rust编程语言在它们之间交换数据。我希望你觉得这对你有帮助!