Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::net::{
- TcpListener,
- TcpStream,
- Shutdown,
- };
- use std::io::prelude::*;
- use std::time::Duration;
- use std::io;
- use std::thread;
- fn main() {
- thread::spawn(|| {
- let listener = TcpListener::bind("127.0.0.1:8088").expect("Cannot bind in start_listener");
- for stream in listener.incoming() {
- let mut s = stream.expect("Cannot accept connection");
- let mut buf = vec![0u8; 10];
- println!("# Connect accepted");
- match s.read(&mut buf) {
- Ok(v) if &buf[0..v] == "read".as_bytes() => {
- println!("## Test for read()");
- s.set_read_timeout(Some(Duration::from_millis(700)));
- reader(&mut s)
- },
- Ok(v) if &buf[0..v] == "exact".as_bytes() => {
- println!("## Test for read_exact()");
- s.set_read_timeout(Some(Duration::from_millis(700)));
- reader_exact(&mut s)
- },
- Ok(v) => println!("Error: unexpected greeting: {} {:?}", String::from_utf8_lossy(&buf[..v]),&buf[..v]),
- Err(r) => println!("Error: cannot read greeting: {}", r)
- }
- };
- });
- thread::sleep(Duration::from_millis(50));
- writer("127.0.0.1:8088", "read");
- writer("127.0.0.1:8088", "exact");
- thread::sleep(Duration::from_millis(1000));
- }
- #[derive(PartialEq,Debug)]
- enum RR {
- Disconnect,
- Read(Vec<u8>),
- Timeout(Vec<u8>),
- Error,
- UnexpectedEof,
- }
- fn reader(mut s: &mut TcpStream) {
- let patterns = [
- RR::Read("1234".as_bytes().to_vec()),
- RR::Timeout("".as_bytes().to_vec()),
- RR::Read("567".as_bytes().to_vec()),
- RR::Timeout("".as_bytes().to_vec()),
- RR::Read("89".as_bytes().to_vec()),
- RR::Timeout("".as_bytes().to_vec()),
- RR::Read("abcde".as_bytes().to_vec()),
- RR::Timeout("".as_bytes().to_vec()),
- RR::Read("fg".as_bytes().to_vec()),
- ];
- for pat in &patterns {
- let r = read(&mut s);
- assert_eq!(pat, &r);
- }
- }
- fn read(mut s: &mut TcpStream) -> RR {
- let mut buf = vec![0u8; 10];
- // case: read with read_timeout
- match s.read(&mut buf) {
- Ok(0) => {
- println!("## read 0 bytes, assume client disconnected");
- RR::Disconnect
- }
- Ok(size) => {
- println!("## read {} bytes: {}, {:?}", size, String::from_utf8_lossy(&buf[0..size]), &buf[0..size]);
- RR::Read(buf[0..size].to_vec())
- },
- Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
- dbg!("## read timeout");
- RR::Timeout("".as_bytes().to_vec())
- },
- Err(e) => {
- println!("## read error: {:?}", e);
- RR::Error
- },
- }
- }
- fn reader_exact(mut s: &mut TcpStream) {
- let patterns = [
- RR::Read("1234".as_bytes().to_vec()),
- RR::Timeout(vec![0, 0, 0, 0]),
- RR::Timeout(vec![b'5',b'6',b'7',0]),
- RR::Timeout(vec![b'8',b'9',0,0]),
- RR::Read("abcd".as_bytes().to_vec()),
- RR::Timeout(vec![b'e',0,0,0]),
- RR::Timeout(vec![b'f',b'g',0,0]),
- RR::UnexpectedEof,
- ];
- for pat in &patterns {
- let r = read_exact(&mut s, 4);
- assert_eq!(pat, &r);
- }
- }
- fn read_exact(mut s: &mut TcpStream, size: usize) -> RR {
- let mut buf = vec![0u8; 10];
- // case: read_exact with read_timeout
- match s.read_exact(&mut buf[..size]) {
- Ok(()) => {
- println!("## aread {} bytes: {}, {:?}", size, String::from_utf8_lossy(&buf[0..size]), &buf[0..size]);
- RR::Read(buf[0..size].to_vec())
- },
- Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof => {
- println!("## read error, assume client disconnected");
- RR::UnexpectedEof
- },
- Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
- // at this point read_exact may write some bytes to buffer but not full - these bytes will be lost
- println!("## read timeout: {}, {:?}", String::from_utf8_lossy(&buf[0..size]), &buf[0..size]);
- RR::Timeout(buf[0..size].to_vec())
- },
- Err(e) => {
- println!("## read error: {:?}", e);
- RR::Error
- },
- }
- }
- fn writer(port: &str, greeting: &str) {
- let mut stream = TcpStream::connect(port).expect(&format!("cannot connect to {}", port));
- stream.set_nodelay(true);
- stream.write(greeting.as_bytes());
- thread::sleep(Duration::from_millis(100));
- let patterns = [
- "1234",
- "567",
- "89",
- "abcde",
- "fg",
- ];
- for i in &patterns {
- stream.write(i.as_bytes()).expect("cannot write");
- thread::sleep(Duration::from_millis(1000));
- }
- stream.shutdown(Shutdown::Both).expect("shutdown call failed");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement