(rust) file transfer via tcp

added lorem.md for tests
This commit is contained in:
2025-05-16 15:56:00 +02:00
committed by scbj
parent 705aea3ba9
commit 954c450b7e
2 changed files with 1448 additions and 8 deletions
+1380
View File
File diff suppressed because it is too large Load Diff
+68 -8
View File
@@ -1,7 +1,5 @@
#![allow(dead_code, unused)] #![allow(dead_code, unused)]
use std::fs::read;
use chrono::{ use chrono::{
DateTime, DateTime,
Local, Local,
@@ -42,21 +40,20 @@ use tokio::{
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
let listener = TcpListener::bind("127.0.0.1:9090").await?; let listener = TcpListener::bind("127.0.0.1:9090").await?;
let file = fs::read("test.md").await?; let file = fs::read("../lorem.md").await?;
tokio::spawn(async move { tokio::spawn(async move {
sleep(Duration::from_secs(2)).await; sleep(Duration::from_secs(1)).await;
let mut connection = TcpStream::connect("127.0.0.1:9090").await.unwrap(); let mut connection = TcpStream::connect("127.0.0.1:9090").await.unwrap();
connection.write_all(&file[..]).await.unwrap(); _ = send_file(&mut connection, file).await;
}); });
let mut read_buffer = [0u8; 2<<16];
match listener.accept().await { match listener.accept().await {
Ok((mut stream, address)) => { Ok((mut stream, address)) => {
println!("accepted connection request from {}", address); println!("accepted connection request from {}", address);
let size = stream.read(&mut read_buffer).await?; let file = receive_file(&mut stream).await?;
fs::write("test-copy.md", &read_buffer[0..size]).await?; fs::write("test-lorem.md", file).await?;
} }
Err(error) => { Err(error) => {
println!("this is unexpected.. {}", error.to_string()); println!("this is unexpected.. {}", error.to_string());
@@ -66,4 +63,67 @@ async fn main() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
async fn receive_file(stream: &mut TcpStream) -> Result<Vec<u8>, anyhow::Error> {
const BUFFER_SIZE: usize = 4096;
let mut buffer = [0u8; BUFFER_SIZE];
let mut index_counter: usize = 0;
let mut processing_buffer = Vec::<u8>::new();
let mut file = Vec::<u8>::new();
let mut size: usize = 0;
loop {
let num_bytes = stream.read(&mut buffer[..]).await?;
processing_buffer.extend(&buffer[0..num_bytes]);
if 0 == index_counter {
size = usize::from_be_bytes(processing_buffer.drain(0..8).collect::<Vec<_>>().try_into().unwrap());
} else {
_ = processing_buffer.drain(0..8);
}
let block_size = usize::from_be_bytes(processing_buffer.drain(0..8).collect::<Vec<_>>().try_into().unwrap());
let index = usize::from_be_bytes(processing_buffer.drain(0..8).collect::<Vec<_>>().try_into().unwrap());
if index_counter != index {
panic!("meh, counter = {index_counter}, index = {index}");
}
file.extend(processing_buffer.drain(0..block_size));
index_counter += 1;
if block_size >= size {
break;
} else {
size -= block_size;
}
}
Ok(file)
}
async fn send_file(stream: &mut TcpStream, mut file: Vec<u8>) -> Result<(), anyhow::Error> {
const BLOCK_SIZE: usize = 2048;
let size: usize = file.len();
let mut remaining = size;
let mut index: usize = 0;
while remaining > 0 {
let mut block = Vec::<u8>::new();
let len = if remaining >= BLOCK_SIZE {
BLOCK_SIZE
} else {
remaining
};
block.extend(size.to_be_bytes());
block.extend(len.to_be_bytes());
block.extend(index.to_be_bytes());
block.extend(file.drain(0..len));
stream.write(&block[..]).await?;
remaining -= len;
index += 1;
}
Ok(())
}