Last active
October 4, 2017 17:30
-
-
Save reeFridge/055fb15bae40056d8b92c73965146c5b to your computer and use it in GitHub Desktop.
Echo server with broadcast feature (it is simple game-data-transfer-server and i am using him as game server for my side-scroller game project)
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
extern crate mio; | |
extern crate byteorder; | |
use byteorder::{ByteOrder, LittleEndian, BigEndian}; | |
use mio::*; | |
use std::io::{self, Read, Write}; | |
use mio::net::{TcpListener, TcpStream}; | |
use std::collections::HashMap; | |
use std::convert::From; | |
// Setup some tokens to allow us to identify which event is | |
// for which socket. | |
const SERVER: Token = Token(0); | |
fn main() { | |
let addr = "127.0.0.1:7001".parse().unwrap(); | |
// Setup the server socket | |
let server = TcpListener::bind(&addr).unwrap(); | |
// Create a poll instance | |
let poll = Poll::new().unwrap(); | |
// Start listening for incoming connections | |
poll.register(&server, SERVER, Ready::readable(), | |
PollOpt::edge()).unwrap(); | |
// Create storage for events | |
let mut events = Events::with_capacity(1024); | |
let mut clients = HashMap::new(); | |
loop { | |
poll.poll(&mut events, None).unwrap(); | |
for event in events.iter() { | |
match event.token() { | |
SERVER => { | |
println!("event: {:?}", event.readiness()); | |
println!("Server token"); | |
println!("new client connected"); | |
let next_index = clients.len() + 1; | |
let new_token = Token(next_index); | |
clients.insert(new_token, match server.accept() { | |
Ok((mut stream, _)) => { | |
poll.register( | |
&stream, | |
new_token, | |
Ready::writable() | Ready::readable(), | |
PollOpt::edge() | |
).unwrap(); | |
let mut buf = [0u8; 8]; | |
BigEndian::write_u64(&mut buf, usize::from(new_token) as u64); | |
stream.write_all(&mut buf).unwrap(); | |
stream.flush().unwrap(); | |
stream | |
}, | |
Err(e) => panic!("failed on accept connection: {}", e) | |
}); | |
}, | |
token => { | |
let ready = event.readiness(); | |
println!("client token: {:?}", token); | |
println!("event: {:?}", ready); | |
if ready.is_hup() || ready.is_error() { | |
println!("client with token {:?} disconnected", &token); | |
clients.remove(&token); | |
} else { | |
if event.readiness().is_readable() { | |
print!("read from [{:?}]: ", &token); | |
let mut message = String::new(); | |
let mut buf = [0u8, 64]; | |
loop { | |
match clients.get_mut(&token).unwrap().read(&mut buf) { | |
Ok(0) => { | |
println!("client with token {:?} disconnected", &token); | |
clients.remove(&token); | |
break; | |
}, | |
Ok(_) => { | |
message.push_str(String::from_utf8_lossy(&mut buf).into_owned().as_str()); | |
}, | |
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { | |
//println!("[end of stream]"); | |
break; | |
}, | |
Err(_) => panic!("Error on read") | |
} | |
} | |
print!("{}", message); | |
if event.readiness().is_writable() { | |
for (t, client) in clients.iter_mut() { | |
if !t.eq(&token) { | |
client.write_all(message.as_bytes()).unwrap(); | |
} | |
} | |
} | |
} | |
} | |
} | |
_ => unreachable!(), | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment