Skip to content

Instantly share code, notes, and snippets.

@Mec-iS
Created February 2, 2023 17:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mec-iS/d04f76d99d0dd08f99e57a7f0e2eecfe to your computer and use it in GitHub Desktop.
Save Mec-iS/d04f76d99d0dd08f99e57a7f0e2eecfe to your computer and use it in GitHub Desktop.
An echo server using Polling (Rust)
use std::collections::HashMap;
use std::net::{TcpListener, TcpStream};
use std::os::unix::io::AsRawFd;
use nix::sys::socket::{setsockopt, sockopt::Nonblock};
use nix::poll::{poll, PollFd, EventFlags};
const STATE_REQ: u32 = 0;
const STATE_RES: u32 = 1;
const STATE_END: u32 = 2;
struct Conn {
fd: i32,
state: u32,
rbuf_size: usize,
rbuf: [u8; 4 + k_max_msg],
wbuf_size: usize,
wbuf_sent: usize,
wbuf: [u8; 4 + k_max_msg],
}
impl Default for Conn {
fn default() -> Self {
Self {
fd: -1,
state: 0,
rbuf_size: 0,
rbuf: [0; 4 + k_max_msg],
wbuf_size: 0,
wbuf_sent: 0,
wbuf: [0; 4 + k_max_msg],
}
}
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let fd = listener.as_raw_fd();
setsockopt(fd, Nonblock, true).unwrap();
let mut fd2conn = HashMap::new();
let mut poll_args = vec![];
loop {
poll_args.clear();
let mut pfd = PollFd::new(fd, EventFlags::POLLIN, 0);
poll_args.push(pfd);
for (_, conn) in &fd2conn {
let mut pfd = PollFd::new(conn.fd, if conn.state == STATE_REQ { EventFlags::POLLIN } else { EventFlags::POLLOUT }, 0);
pfd.set_flags(pfd.flags() | EventFlags::POLLERR);
poll_args.push(pfd);
}
let rv = poll(&mut poll_args, 1000).unwrap();
if rv < 0 {
panic!("poll() error");
}
for i in 1..poll_args.len() {
if poll_args[i].revents().is_empty() {
continue;
}
let conn = fd2conn.get_mut(&poll_args[i].fd()).unwrap();
connection_io(conn);
if conn.state == STATE_END {
fd2conn.remove(&conn.fd);
nix::unistd::close(conn.fd).unwrap();
}
}
if poll_args[0].revents().contains(EventFlags::POLLIN) {
let (conn_stream, _) = listener.accept().unwrap();
let conn = Conn {
fd: conn_stream.as_raw_fd(),
..Default::default()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment