Skip to content

Instantly share code, notes, and snippets.

@critiqjo
Last active August 10, 2021 15:26
Show Gist options
  • Save critiqjo/1fa4263043f065e7fce6 to your computer and use it in GitHub Desktop.
Save critiqjo/1fa4263043f065e7fce6 to your computer and use it in GitHub Desktop.
Buffered Client-Server
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!")
}
}
}
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);
}
}
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);
}
}
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);
}
}
}
}
#[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