Created
November 20, 2023 19:19
-
-
Save alex-s168/7975bfb0b03021aca8c4bf355a2d2d9f to your computer and use it in GitHub Desktop.
rust basic read only file server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::net::{TcpListener,TcpStream,Shutdown}; | |
use std::result::Result; | |
use std::io::{Write,Read,BufRead,BufReader}; | |
use std::thread; | |
use std::io; | |
use std::process::exit; | |
use std::path::Path; | |
use std::fs::{File,read_dir}; | |
use std::env; | |
fn client(mut stream: TcpStream) { | |
let _ = writeln!(stream, "hello").map_err(|err| { | |
eprintln!("ERR: could not send message to client: {err}"); | |
}); | |
let reader = BufReader::new(&stream); | |
for l in reader.lines() { | |
if l.is_err() { | |
continue; | |
} | |
let lx = l.unwrap(); | |
let mut command = lx.split(' '); | |
let argc = command.to_owned().count(); | |
if argc == 0 { | |
let _ = writeln!(&stream, "invalid cmd"); | |
continue; | |
} | |
let inst = command.next().unwrap(); | |
if inst == "quit" { | |
let _ = stream.shutdown(Shutdown::Both).map_err(|err| { | |
eprintln!("ERR: could not close connection (requested by client): {}", err); | |
}); | |
return; | |
} | |
if argc < 2 { | |
let _ = writeln!(&stream, "invalid cmd"); | |
continue; | |
} | |
let mut arg = String::new(); | |
for _ in 1..argc { | |
arg.push_str(command.next().unwrap()); | |
} | |
if inst == "file" { | |
let path = Path::new(&arg); | |
if !path.is_file() { | |
let _ = writeln!(&stream, "not a file"); | |
continue; | |
} | |
let mut file = File::open(path).unwrap(); | |
let len = file.metadata().unwrap().len() as usize; | |
let _ = writeln!(&stream, "len: {}", len); | |
let mut string = String::with_capacity(len); | |
if file.read_to_string(&mut string).is_err() { | |
let _ = writeln!(&stream, "error reading file"); | |
continue; | |
} | |
let _ = writeln!(&stream, "{}", string); | |
} | |
else if inst == "list" { | |
let path = Path::new(&arg); | |
if !path.is_dir() { | |
let _ = writeln!(&stream, "not a directory"); | |
continue; | |
} | |
let paths = read_dir(path).unwrap(); | |
for p in paths { | |
let _ = writeln!(&stream, "{}", p.unwrap().path().display()); | |
} | |
} | |
else { | |
let _ = writeln!(&stream, "invalid cmd"); | |
} | |
} | |
} | |
fn main() -> Result<(), ()> { | |
let mut args = env::args(); | |
let _ = args.next(); | |
if args.len() != 1 { | |
eprintln!("Invalid arguments! Usage: [ip]:[port]"); | |
exit(1); | |
} | |
let addr = args.next().unwrap(); | |
let listener = TcpListener::bind(&addr).map_err(|err| { | |
eprintln!("ERR: Could not bind {addr} {err}"); | |
})?; | |
let mut threads: Vec<thread::JoinHandle<_>> = Vec::new(); | |
thread::spawn(|| { | |
let stdin = io::stdin(); | |
let lines = stdin.lock().lines(); | |
for line in lines { | |
let cmd = line.unwrap(); | |
if cmd == "exit" { | |
exit(1); | |
} | |
else if cmd == "help" { | |
println!("exit Stops the server"); | |
} | |
else { | |
println!("Enter \"help\" for a list of available commands!"); | |
} | |
} | |
}); | |
for stream in listener.incoming() { | |
if stream.is_err() { | |
eprintln!("ERR: broken stream"); | |
continue; | |
} | |
threads.push(thread::spawn(|| client(stream.unwrap()))); | |
} | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment