Skip to content

Instantly share code, notes, and snippets.

@reeFridge
Last active October 4, 2017 17:30
Show Gist options
  • Save reeFridge/055fb15bae40056d8b92c73965146c5b to your computer and use it in GitHub Desktop.
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)
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