(rust) file transfer via tcp
added lorem.md for tests
This commit is contained in:
+68
-8
@@ -1,7 +1,5 @@
|
||||
#![allow(dead_code, unused)]
|
||||
|
||||
use std::fs::read;
|
||||
|
||||
use chrono::{
|
||||
DateTime,
|
||||
Local,
|
||||
@@ -42,21 +40,20 @@ use tokio::{
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
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 {
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
|
||||
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 {
|
||||
Ok((mut stream, address)) => {
|
||||
println!("accepted connection request from {}", address);
|
||||
let size = stream.read(&mut read_buffer).await?;
|
||||
fs::write("test-copy.md", &read_buffer[0..size]).await?;
|
||||
let file = receive_file(&mut stream).await?;
|
||||
fs::write("test-lorem.md", file).await?;
|
||||
}
|
||||
Err(error) => {
|
||||
println!("this is unexpected.. {}", error.to_string());
|
||||
@@ -66,4 +63,67 @@ async fn main() -> anyhow::Result<()> {
|
||||
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(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user