使用Rust构建简单的文件传输系统

使用Rust编程语言创建一个简单的文件传输系统。Rust以其性能、安全性和并发性功能而闻名,是构建网络应用程序的绝佳选择。

概述

我们的文件传输系统将包括一个客户端和一个服务器。客户端将向服务器发送文件,服务器将保存接收到的文件。

使用的技术:

  • Rust编程语言
  • 标准库(std::netstd::fsstd::io
  • TCP/IP网络

实现

服务器端

首先从服务器端实现开始。服务器将监听传入的连接,并将接收到的文件保存到磁盘上。

Command::Server {
            host,
            port
        } =>{
            let server = format!("{}:{}",host.clone().unwrap(),port.clone().unwrap());
            let listener = TcpListener::bind(server.as_str()).expect("ip绑定失败");
            //incoming返回此侦听器上接收的连接的迭代器。
            // 返回的迭代器永远不会返回 None,也不会生成对等方的 SocketAddr 结构。遍历它等效于在循环中调用 TcpListener::accept。
            for stream in listener.incoming(){
                match stream {
                    Ok(stream) =>{
                        handle_client(stream);
                    }
                    Err(e) => {
                        eprintln!("tcp 连接失败: {}", e);
                    }
                }
            }
        },
use std::fs::File;
use std::io::{Read, Write};
use std::net::TcpStream;

struct FileMessage {
    filename: String,
    file_size: u64,
    file_data: Vec<u8>,
}

fn encode_file_message(msg: FileMessage) -> Vec<u8> {
    let mut encoded_message = Vec::<u8>::new();
    encoded_message.push(msg.filename.len() as u8);
    encoded_message.extend_from_slice(&msg.filename.as_bytes());
    encoded_message.extend_from_slice(&msg.file_size.to_le_bytes());
    encoded_message.extend_from_slice(&msg.file_data);
    encoded_message
}

fn decode_file_message(data: &[u8]) -> FileMessage {
    let filename_length = data[0] as usize;
    let filename = String::from_utf8_lossy(&data[1..1 + filename_length]).into_owned();
    let file_size = u64::from_le_bytes(data[1 + filename_length..9 + filename_length].try_into().unwrap());
    let file_data = data[9 + filename_length..].to_vec();
    FileMessage {
        filename,
        file_size,
        file_data,
    }
}

pub fn handle_client(mut stream: TcpStream) {
    let mut buffer = [0; 1024];
    match stream.read(&mut buffer) {
        Ok(bytes_read) => {
            let received_data = &buffer[..bytes_read];
            let received_message = decode_file_message(received_data);
            save_file(&received_message.filename, &received_message.file_data).expect("Error saving file");
        }
        Err(e) => panic!("读取字节流失败:{}", e)
    }
}

fn save_file(filename: &str, data: &[u8]) -> std::io::Result<()> {
    let file = format!("{}+successfully", filename);
    let mut file = File::create(file)?;
    file.write_all(data)?;
    Ok(())
}

客户端

接下来,实现客户端。客户端将与服务器建立连接并发送文件。

Command::Client {
            send,
            host,
            port
        } =>{
            let server = format!("{}:{}",host.clone().unwrap(),port.clone().unwrap());
            let mut stream = TcpStream::connect(server).unwrap();
            if let Some(filename) = send{
                match send_file(&mut stream,filename) {
                    Ok(_rs) =>{
                        println!("发送成功!")
                    }
                    Err(e) => panic!("文件发送失败:{}",e)
                }
            }
        },
use std::fs::File;
use std::io::{Read, Write};
use std::net::TcpStream;

struct FileMessage {
    filename: String,
    file_size: u64,
    file_data: Vec<u8>,
}

fn encode_file_message(msg: FileMessage) -> Vec<u8> {
    let mut encoded_message = Vec::<u8>::new();
    encoded_message.push(msg.filename.len() as u8);
    encoded_message.extend_from_slice(&msg.filename.as_bytes());
    encoded_message.extend_from_slice(&msg.file_size.to_le_bytes());
    encoded_message.extend_from_slice(&msg.file_data);
    encoded_message
}

fn decode_file_message(data: &[u8]) -> FileMessage {
    let filename_length = data[0] as usize;
    let filename = String::from_utf8_lossy(&data[1..1 + filename_length]).into_owned();
    let file_size = u64::from_le_bytes(data[1 + filename_length..9 + filename_length].try_into().unwrap());
    let file_data = data[9 + filename_length..].to_vec();
    FileMessage {
        filename,
        file_size,
        file_data,
    }
}

pub fn send_file(stream: &mut TcpStream, filename: &str) -> std::io::Result<()> {
    let mut file = File::open(filename)?;
    let mut file_data = Vec::new();
    file.read_to_end(&mut file_data)?;

    let file_message = FileMessage {
        filename: filename.to_owned(),
        file_size: file_data.len() as u64,
        file_data,
    };

    let encoded_message = encode_file_message(file_message);

    stream.write_all(&encoded_message)?;

    Ok(())
}

通信协议

文件传输系统使用了一个简单的通信协议:

  1. 消息结构:每个消息包括:

    • 文件名长度(1字节)
    • 文件名(可变长度)
    • 文件大小(8字节,小端序)
    • 文件数据(可变长度)
  2. 编码:在通过网络发送之前,将FileMessage结构编码为字节数组。

  3. 解码:接收到的字节数组被解码回FileMessage结构。

结论

使用Rust构建了一个简单的文件传输系统。实现了客户端和服务器端,并探讨了用于在网络上传输文件的通信协议。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值