-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.rs
70 lines (51 loc) · 2.07 KB
/
server.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use std::env;
use std::fs::File;
use std::io::{self, BufReader, BufWriter, Read, Write};
use std::net::TcpListener;
use std::path::Path;
use std::process;
const MAX_BYTES_TO_READ_AT_ONCE: u64 = u64::pow(10, 7);
fn get_file_and_filesize(file_location: &str) -> Result<(File, &str, u64), io::Error> {
let file_path = Path::new(file_location);
let file_size = file_path.metadata()?.len();
let file_absolute_path = file_path.canonicalize()?;
let file_to_send = File::open(file_absolute_path)?;
let file_name = file_path.file_name().unwrap().to_str().unwrap();
Ok((file_to_send, file_name, file_size))
}
fn send_file_to_client(file_location: &str) -> Result<(), io::Error> {
let (mut file_to_send, file_name, file_size) = get_file_and_filesize(file_location)?;
let listener = TcpListener::bind("192.168.0.102:60000")?;
let (mut tcp_socket, _socket_addr) = listener.accept()?;
tcp_socket.write_fmt(format_args!("{}\n", file_name))?;
// To receive "ACK" from client.
let mut ack_buf = [0u8; 3];
tcp_socket.read_exact(&mut ack_buf)?;
let mut writer = BufWriter::with_capacity(MAX_BYTES_TO_READ_AT_ONCE as usize, &tcp_socket);
let mut reader =
BufReader::with_capacity(MAX_BYTES_TO_READ_AT_ONCE as usize, &mut file_to_send);
let mut buffer = [0u8; MAX_BYTES_TO_READ_AT_ONCE as usize];
let mut remaining_bytes_to_read = file_size;
while remaining_bytes_to_read >= MAX_BYTES_TO_READ_AT_ONCE {
reader.read_exact(&mut buffer)?;
writer.write_all(&buffer)?;
remaining_bytes_to_read -= MAX_BYTES_TO_READ_AT_ONCE;
}
if remaining_bytes_to_read != 0 {
let mut last_buffer = Vec::<u8>::new();
reader.read_to_end(&mut last_buffer)?;
writer.write_all(&last_buffer)?;
}
Ok(())
}
fn main() -> Result<(), String> {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
eprintln!("Usage: server filename");
process::exit(1);
}
if let Err(err) = send_file_to_client(&args[1]) {
return Err(err.to_string());
}
Ok(())
}