Last active
August 10, 2021 15:26
-
-
Save critiqjo/1fa4263043f065e7fce6 to your computer and use it in GitHub Desktop.
Buffered Client-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
fn main() { | |
let mut ifx = Ifx::new("localhost:8080"); | |
for i in 0..20 { | |
ifx.send(i); | |
} | |
} | |
use std::fmt::Display; | |
use std::io::{BufRead, BufReader, Lines, Write}; | |
use std::net::TcpStream; | |
struct Ifx { | |
stream: TcpStream, | |
lines: Lines<BufReader<TcpStream>>, | |
} | |
impl Ifx { | |
fn new(address: &str) -> Ifx { | |
let stream = TcpStream::connect(address).unwrap(); | |
Ifx { | |
stream: stream.try_clone().unwrap(), | |
lines: BufReader::new(stream).lines(), | |
} | |
} | |
fn send<T: Display>(&mut self, v: T) { | |
let _ = write!(&mut self.stream, "{}\r\n", v); | |
if let Some(Ok(reply)) = self.lines.next() { | |
println!("{}", reply); | |
} else { | |
panic!("Bad reply from the 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::io::{BufRead, BufReader, Write}; | |
use std::net::TcpListener; | |
fn main() { | |
let listener = TcpListener::bind("localhost:8080").unwrap(); | |
println!("Waiting..."); | |
for stream in listener.incoming() { | |
let mut stream = stream.unwrap(); | |
let addr = stream.peer_addr().unwrap(); | |
println!("Connected from {}", addr); | |
let lines = BufReader::new(stream.try_clone().unwrap()).lines(); | |
for line in lines { | |
if let Ok(line) = line { | |
let _ = write!(&mut stream, "got {:?}\r\n", line); | |
} else { break; } | |
} | |
println!("{} disconnected!", addr); | |
} | |
} |
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::io::{Read, Write}; | |
use std::net::TcpListener; | |
fn main() { | |
let listener = TcpListener::bind("localhost:8080").unwrap(); | |
println!("Waiting..."); | |
for stream in listener.incoming() { | |
let mut stream = stream.unwrap(); | |
let addr = stream.peer_addr().unwrap(); | |
println!("Connected from {}", addr); | |
loop { | |
let mut bytes = [0u8; 4]; | |
let line = match stream.read(&mut bytes) { | |
Ok(n) if n > 0 => { | |
let (s, _) = bytes.split_at(n); | |
String::from_utf8(s.to_vec()) | |
}, | |
_ => break, | |
}; | |
if let Ok(line) = line { | |
let _ = write!(&mut stream, "got {:?}\r\n", line); | |
} else { break; } | |
} | |
println!("{} disconnected!", addr); | |
} | |
} |
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::io::{Read, Write, ErrorKind}; | |
use std::net::TcpListener; | |
fn main() { | |
let listener = TcpListener::bind("localhost:8080").unwrap(); | |
println!("Waiting..."); | |
for stream in listener.incoming() { | |
let mut stream = stream.unwrap(); | |
let addr = stream.peer_addr().unwrap(); | |
println!("Connected from {}", addr); | |
let mut read_until = ReadUntil::new(); | |
loop { | |
let mut bytes = vec![]; | |
let line = match read_until.read_until(&mut stream, b'\n', &mut bytes) { | |
Ok(n) if n > 0 => String::from_utf8(bytes), | |
_ => break, | |
}; | |
if let Ok(line) = line { | |
let _ = write!(&mut stream, "got {:?}\r\n", line); | |
} else { break; } | |
} | |
println!("{} disconnected!", addr); | |
} | |
} | |
struct ReadUntil { | |
slice: [u8; 8], | |
end: usize, | |
} | |
impl ReadUntil { | |
fn new() -> ReadUntil { | |
ReadUntil { slice: [0; 8], end: 0 } | |
} | |
fn read_until<R>(&mut self, stream: &mut R, delim: u8, bytes: &mut Vec<u8>) | |
-> std::io::Result<usize> where R: Read { | |
let bytes_init_len = bytes.len(); | |
let mut read = bytes.len(); | |
let mut excess = 0; | |
let mut bytes_cap = bytes.capacity(); | |
unsafe { bytes.set_len(bytes_cap); } | |
loop { | |
if bytes_cap < read + 8 { | |
let cap_add = std::cmp::max(bytes_cap, 8); | |
bytes.reserve(cap_add); | |
bytes_cap = bytes.capacity(); | |
unsafe { bytes.set_len(bytes_cap); } | |
} | |
let (done, got) = { | |
let available = if self.end > 0 { | |
bytes[read..read + 8].iter_mut().zip(self.slice[..self.end].iter()) | |
.fold((), |_, (x, y)| *x = *y); // copy slice -> bytes | |
let len = self.end; | |
self.end = 0; | |
&bytes[read..read + len] | |
} else { | |
match stream.read(&mut bytes[read..read + 8]) { | |
Ok(n) => &bytes[read..read + n], | |
Err(ref e) if e.kind() == ErrorKind::Interrupted | |
=> continue, | |
Err(e) => return Err(e), | |
} | |
}; | |
read += available.len(); | |
match available.iter().position(|&x| x == delim) { | |
Some(i) => { | |
excess = available.len() - i - 1; | |
(true, available.len()) | |
}, | |
None => (false, available.len()), | |
} | |
}; | |
if done || got == 0 { | |
if excess > 0 { | |
self.slice.iter_mut().zip(bytes[read - excess..read].iter()) | |
.fold((), |_, (x, &y)| *x = y); // copy excess bytes -> slice | |
self.end = excess; | |
} | |
unsafe { bytes.set_len(read - excess); } | |
return Ok(bytes.len() - bytes_init_len); | |
} | |
} | |
} | |
} |
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
#[macro_use(read_lines)] | |
extern crate lines; | |
use lines::linereader::LineReader; | |
use std::io::Write; | |
use std::net::TcpListener; | |
fn main() { | |
let listener = TcpListener::bind("localhost:8080").unwrap(); | |
println!("Waiting..."); | |
for stream in listener.incoming() { | |
let mut stream = stream.unwrap(); | |
let addr = stream.peer_addr().unwrap(); | |
println!("Connected from {}", addr); | |
read_lines!(line in LineReader::new(stream.try_clone().unwrap()), { | |
let line = std::str::from_utf8(line.unwrap()).unwrap(); | |
let _ = write!(&mut stream, "got {:?}\r\n", line); | |
}); | |
println!("{} disconnected!", addr); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment