Learn how to build real-world applications with VSTP through these step-by-step tutorials. Each tutorial focuses on a specific use case and demonstrates best practices.
In this tutorial, we'll build a simple chat application using VSTP's TCP mode with automatic message routing.
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone)]
pub struct ChatMessage {
pub from: String,
pub content: String,
pub timestamp: u64,
}
#[derive(Serialize, Deserialize)]
pub struct UserJoin {
pub username: String,
}
#[derive(Serialize, Deserialize)]
pub struct UserLeave {
pub username: String,
}use vstp::easy::VstpServer;
use std::collections::HashMap;
use tokio::sync::Mutex;
type ConnectedUsers = Arc<Mutex<HashMap<String, String>>>;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let users = Arc::new(Mutex::new(HashMap::new()));
let server = VstpServer::bind_tcp("127.0.0.1:8080").await?;
println!("Chat server running on 127.0.0.1:8080");
server.serve(move |msg: ChatMessage| {
let users = users.clone();
async move {
// Broadcast message to all connected users
println!("{}: {}", msg.from, msg.content);
Ok(msg)
}
}).await?;
Ok(())
}use vstp::easy::VstpClient;
use std::io::{self, BufRead};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = VstpClient::connect_tcp("127.0.0.1:8080").await?;
let stdin = io::stdin();
println!("Enter your username:");
let mut username = String::new();
stdin.lock().read_line(&mut username)?;
let username = username.trim().to_string();
// Send join message
client.send(UserJoin { username: username.clone() }).await?;
// Start message receiving task
let client_recv = client.clone();
tokio::spawn(async move {
while let Ok(msg) = client_recv.receive::<ChatMessage>().await {
if msg.from != username {
println!("{}: {}", msg.from, msg.content);
}
}
});
// Handle user input
for line in stdin.lock().lines() {
let content = line?;
if content == "/quit" {
break;
}
let msg = ChatMessage {
from: username.clone(),
content,
timestamp: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)?
.as_secs(),
};
client.send(msg).await?;
}
Ok(())
}Learn how to build a secure file transfer system using VSTP's reliable TCP mode with progress tracking.
#[derive(Serialize, Deserialize)]
pub struct FileInfo {
pub filename: String,
pub size: u64,
pub checksum: String,
}
#[derive(Serialize, Deserialize)]
pub struct FileChunk {
pub chunk_id: u32,
pub data: Vec<u8>,
pub is_last: bool,
}
#[derive(Serialize, Deserialize)]
pub struct TransferProgress {
pub bytes_transferred: u64,
pub total_bytes: u64,
}use std::path::Path;
use sha2::{Sha256, Digest};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let server = VstpServer::bind_tcp("127.0.0.1:8080").await?;
server.serve(|chunk: FileChunk| async move {
// Save chunk to file
let mut file = tokio::fs::OpenOptions::new()
.create(true)
.append(true)
.open("received_file").await?;
file.write_all(&chunk.data).await?;
// Send progress update
let progress = TransferProgress {
bytes_transferred: chunk.chunk_id as u64 * 1024,
total_bytes: 0, // Would be set from initial FileInfo
};
Ok(progress)
}).await?;
Ok(())
}Build a high-performance data streaming system using VSTP's UDP mode for low-latency communication.
#[derive(Serialize, Deserialize)]
pub struct SensorData {
pub sensor_id: String,
pub timestamp: u64,
pub temperature: f32,
pub humidity: f32,
pub pressure: f32,
}
#[derive(Serialize, Deserialize)]
pub struct DataStream {
pub stream_id: String,
pub data: Vec<SensorData>,
}#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let server = VstpServer::bind_udp("127.0.0.1:8080").await?;
server.serve(|data: SensorData| async move {
// Process real-time data
println!("Sensor {}: {:.2}°C, {:.2}%",
data.sensor_id, data.temperature, data.humidity);
// Store in database or forward to other systems
store_sensor_data(&data).await?;
Ok(data)
}).await?;
Ok(())
}
async fn store_sensor_data(data: &SensorData) -> Result<(), Box<dyn std::error::Error>> {
// Implementation for storing data
Ok(())
}Learn how to use VSTP for inter-service communication in a microservices architecture.
#[derive(Serialize, Deserialize)]
pub struct ServiceRequest {
pub service_name: String,
pub method: String,
pub payload: serde_json::Value,
pub request_id: String,
}
#[derive(Serialize, Deserialize)]
pub struct ServiceResponse {
pub request_id: String,
pub result: Result<serde_json::Value, String>,
}use std::collections::HashMap;
type ServiceRegistry = Arc<Mutex<HashMap<String, String>>>;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let registry = Arc::new(Mutex::new(HashMap::new()));
let server = VstpServer::bind_tcp("127.0.0.1:8080").await?;
server.serve(move |req: ServiceRequest| {
let registry = registry.clone();
async move {
// Route request to appropriate service
let service_addr = registry.lock().await
.get(&req.service_name)
.ok_or("Service not found")?;
// Forward request and return response
let response = forward_request(service_addr, &req).await?;
Ok(response)
}
}).await?;
Ok(())
}Build a robust IoT device communication system with automatic reconnection and data buffering.
#[derive(Serialize, Deserialize)]
pub struct DeviceStatus {
pub device_id: String,
pub battery_level: u8,
pub signal_strength: i8,
pub last_seen: u64,
}
#[derive(Serialize, Deserialize)]
pub struct DeviceCommand {
pub device_id: String,
pub command: String,
pub parameters: serde_json::Value,
}#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let server = VstpServer::bind_tcp("0.0.0.0:8080").await?;
server.serve(|status: DeviceStatus| async move {
// Update device status in database
update_device_status(&status).await?;
// Check for pending commands
if let Some(command) = get_pending_command(&status.device_id).await? {
return Ok(command);
}
Ok(DeviceCommand {
device_id: status.device_id,
command: "heartbeat".to_string(),
parameters: serde_json::Value::Null,
})
}).await?;
Ok(())
}Ready to build your own application? Check out these resources: