Skip to content

Instantly share code, notes, and snippets.

@seriyps
Last active November 17, 2022 10:08
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save seriyps/fd6d29442e16c44ba400 to your computer and use it in GitHub Desktop.
Save seriyps/fd6d29442e16c44ba400 to your computer and use it in GitHub Desktop.
Simple concurrent TCP echo server (rust 0.11)
#![feature(phase)]
#[phase(plugin, link)] extern crate log;
extern crate green;
extern crate rustuv;
use std::io;
use std::os;
use std::io::{Listener,Acceptor,TcpStream};
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
green::start(argc, argv, rustuv::event_loop, main)
}
fn main() {
let args = os::args();
if args.len() < 3 {
println!("Usage: {} <ip> <port>", args[0]);
os::set_exit_status(1);
return
}
let host = args[1].as_slice();
let port = from_str::<u16>(args[2].as_slice()).unwrap();
let sock = io::TcpListener::bind(host, port).unwrap();
let mut acceptor = sock.listen();
debug!("Listening...");
for stream in acceptor.incoming() {
match stream {
Err(e) => warn!("Accept err {}", e),
Ok(stream) => {
spawn(proc() {
println!("{}", handle_client(stream));
})
}
}
}
}
type Buf = [u8, ..10240];
fn handle_client(mut stream: io::TcpStream) -> io::IoResult<()> {
info!("New client {}", stream.peer_name());
let mut buf: Buf = [0u8, ..10240];
let (child_tx, parent_rx) = channel::<Buf>();
let (parent_tx, child_rx) = channel::<Buf>();
spawn(proc() {
// if this `deschedule` will be commented, only one CPU core will be used (rust 0.11)
std::task::deschedule();
for mut buf in child_rx.iter() {
for _ in range::<u8>(0, 20) {
buf.reverse();
}
child_tx.send(buf);
};
});
loop {
let got = try!(stream.read(buf));
if got == 0 {
// Is it possible? Or IoError will be raised anyway?
break
}
// outsource CPU-heavy work to separate task, because current green+libuv
// implementation bind all IO tasks to one scheduler (rust 0.11)
// see https://botbot.me/mozilla/rust/2014-08-01/?msg=18995736&page=11
parent_tx.send(buf);
let to_send: Buf = parent_rx.recv();
try!(stream.write(to_send.slice(0, got)));
}
Ok(())
}
@ferrouswheel
Copy link

Tried to get this working with rust 1.2.0, but there are the following issues:

  • green, rustuv no longer exist in rust standard library. Looks like "the external library" they mention is here but it hasn't been updated in a while.
  • proc() no longer exists, and needs to be replaced by ||
  • the Buf type declaration should be type Buf = [u8; 10240];

Haven't discovered an alternative with mio or something yet, but wanted to comment to save other people time.

@seriyps
Copy link
Author

seriyps commented Aug 31, 2015

@ferouswheel yep. This worked with Rust 0.11. For now it's not possible to write smth equal using just Rust standard library.

@dariusc93
Copy link

You can use several libraries to replace green or rustuv. mioco is a good alt to those two. If you want to get completely low level, you could make bindings around libev

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment