How can I specify lifetimes in a for loop? I'm trying to multithread ports, but keep running into lifetime issues.
pub fn connect_server(&self) {
for x in 58350..58360 {
thread::spawn(|| {
match TcpListener::bind(self.local_ip.to_string() + &x.to_string()) {
Ok(socket) => {
for stream in socket.accept() {
println!("received packet: {:?}", stream);
}
},
Err(error) => panic!("Failed to connect socket: {}", error)
}
});
thread::sleep(Duration::from_millis(1));
}
}
error:
borrowed data escapes outside of associated function
`self` escapes the associated function body here
Generate the bind address outside the thread::spawn closure, and use a move closure rather than capturing by reference:
pub fn connect_server(&self) {
for x in 58350..58360 {
let bind_address = format!("{}{}", self.local_ip, x);
thread::spawn(move || {
match TcpListener::bind(bind_address) {
Ok(socket) => {
for stream in socket.accept() {
println!("received packet: {:?}", stream);
}
},
Err(error) => panic!("Failed to connect socket: {}", error)
}
});
thread::sleep(Duration::from_millis(1));
}
}
I can't receive message only one.
When I use 2 Thread first is only send value, second thread only recv value.
What is problem?
let (tx, mut rx) = broadcast::channel(1); // bradcast
let handle = tokio::spawn(async move {
let mut valu = 10;
loop{
valu += 10;
tx.send(valu).unwrap();
thread::sleep(Duration::from_secs(1));
if(valu >= 100){
break;
}
}
});
let handle1 = tokio::spawn(async move{
loop {
// first message recv and stuck
let _result = rx.recv().await;
match _result {
Ok(value)=>{
println!("=====> : {}", value);
},
Err(e)=>{
println!("err : {}", e );
break;
}
}
}
});
`
Never, ever, use std::thread::sleep() in async code. It blocks.
If you use tokio::time::sleep(), it works:
let (tx, mut rx) = broadcast::channel(1); // bradcast
let handle = tokio::spawn(async move {
let mut valu = 10;
loop {
valu += 10;
tx.send(valu).unwrap();
tokio::time::sleep(Duration::from_seconds(1)).await;
if valu >= 100 {
break;
}
}
});
let handle1 = tokio::spawn(async move {
loop {
let _result = rx.recv().await;
match _result {
Ok(value) => {
println!("=====> : {}", value);
}
Err(e) => {
println!("err : {}", e);
break;
}
}
}
});
I'm trying to check if a variable b of a type Option<A> is equal to a of the same type A or None. It would seem idiomatic to use a match statement with multi pattern Some(a) | None, but I can't find a way to make it work.
Is there a way to express this pattern using match or should I just use a normal if pattern?
Example (also in https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=217b4559a73d59409f1d6afe7365d57c):
fn main() {
let a = 3;
let b = Some(5);
// Works but has code duplication
match b {
Some(b_val) if b_val == a => {
println!("do something");
}
None => {
println!("do something");
}
Some(_) => {
println!("do something else");
}
}
// Works but not very idiomatic
if b.is_none() || b.unwrap() == a {
println!("do something");
} else {
println!("do something else");
}
// Does not work
match b {
Some(b_val) if b_val == a | None => {
println!("do something");
}
Some(_) => {
println!("do something else");
}
}
}
I can only come up with a const a:
fn main() {
const a: i32 = 3;
let b = Some(5);
match b {
Some(a) | None => {
println!("do something");
}
_ => {
println!("do something else");
}
}
}
Or use if:
fn main() {
let a = 3;
let b = Some(5);
if b == None || b == Some(a) {
println!("do something");
} else {
println!("do something else");
}
}
Output:
do something else
You can check inequality instead of equality:
match b {
Some(b_val) if b_val != a => {
println!("do something else");
}
_ => {
println!("do something");
}
}
I'm writing a HTTP server and I want to have one thread per CPU and each thread controls a separate epoll instance. I've implemented a test version of edge-triggered epoll using the nix crate, but I don't understand whats wrong with it.
When I'm testing this with ab (ab -n 200000 -c 1000) it works fast,
but at the end of testing epoll freezes. I don't know whats wrong, maybe I've broken the epoll state or I need to use the inner states of the client?
extern crate nix;
use nix::errno::Errno;
use nix::fcntl::*;
use nix::sys::epoll::EpollCreateFlags;
use nix::sys::epoll::*;
use nix::sys::socket::sockopt::ReuseAddr;
use nix::sys::socket::*;
use nix::unistd::close;
use nix::unistd::{read, write};
use nix::Error;
use std::collections::HashMap;
use std::os::unix::io::RawFd;
use std::thread;
const BUFSIZE: usize = 16384;
#[derive(Hash, Eq, PartialEq, Debug, Clone, Copy)]
pub enum State {
Read,
Write,
}
#[derive(Clone, Debug)]
pub struct Client {
pub readed: Vec<u8>,
pub state: State,
}
impl Client {
fn new() -> Self {
Client {
readed: Vec::new(),
state: State::Read,
}
}
}
fn socket_to_nonblock(sock: RawFd) -> Result<(), nix::Error> {
let flags = match fcntl(sock, F_GETFL) {
Ok(fl) => fl,
Err(err) => return Err(err),
};
let new_flags = flags | OFlag::O_NONBLOCK.bits();
let new_flags = OFlag::from_bits(new_flags).unwrap();
match fcntl(sock, F_SETFL(new_flags)) {
Ok(_) => return Ok(()),
Err(err) => return Err(err),
}
}
fn epoll_loop(server_sock: RawFd) -> nix::Result<()> {
let mut clients: HashMap<RawFd, Client> = HashMap::new(); //SockFlag::EPOLLET
let epfd = epoll_create1(EpollCreateFlags::from_bits(0).unwrap())?;
let mut ev = EpollEvent::new(
EpollFlags::EPOLLIN | EpollFlags::EPOLLOUT,
server_sock as u64,
);
epoll_ctl(epfd, EpollOp::EpollCtlAdd, server_sock, &mut ev)?;
let mut epoll_events = vec![EpollEvent::empty(); 1024];
let buffer = [0; BUFSIZE];
let critical_error = false;
let mut accepted = 0;
let mut closed = 0;
let mut refused = 0;
loop {
let nfds = match epoll_wait(epfd, &mut epoll_events, -1) {
Ok(n) => n,
Err(e) => {
println!("Err wait {:?}", e);
panic!();
}
};
for i in 0..nfds {
let cur_socket = epoll_events[i].data() as i32;
let cur_event = epoll_events[i].events();
if cur_event == cur_event & EpollFlags::EPOLLERR
|| cur_event == cur_event & EpollFlags::EPOLLHUP
|| cur_event != cur_event & (EpollFlags::EPOLLIN | EpollFlags::EPOLLOUT)
{
println!("error big if {:?}", cur_event);
close(epoll_events[i].data() as i32);
continue;
}
if server_sock == cur_socket {
loop {
let client_fd = match accept(server_sock) {
Ok(client) => {
accepted += 1;
if (client < 0) {
println!("JOPA");
panic!();
}
println!(
"Accepted {:?} Closed {:?} Dif: {:?} Refused {:?} Events len: {:?}",
accepted,
closed,
accepted - closed,
refused,
nfds
);
client
}
Err(err) => {
refused += 1;
println!("Error accept {:?}", err);
break;
}
};
match socket_to_nonblock(client_fd) {
Ok(_) => {}
Err(err) => println!("Non block err {:?}", err),
}
let mut ev = EpollEvent::new(
EpollFlags::EPOLLIN | EpollFlags::EPOLLET,
client_fd as u64,
);
match epoll_ctl(epfd, EpollOp::EpollCtlAdd, client_fd, &mut ev) {
Ok(e) => {}
Err(err) => println!("Server accept ctl {:?}", err),
}
println!("{:?}", clients.insert(client_fd, Client::new()));
break;
}
println!("loop breaked");
continue;
}
if cur_event == cur_event & EpollFlags::EPOLLIN {
let mut buf: [u8; 2048] = [0; 2048];
let client = clients.get_mut(&cur_socket).unwrap();
loop {
let mut total_len = client.readed.len();
let size = match read(cur_socket, &mut buf[total_len..]) {
Ok(size) => {
client.readed.extend_from_slice(&buf[..size]);
if (size == 0) {
break;
}
}
Err(e) => break,
};
}
let req = std::str::from_utf8(&client.readed.as_slice())
.unwrap()
.to_string();
if !(req.find("\n\n").is_some() || req.find("\r\n\r\n").is_some()) {
continue;
}
let mut ev = EpollEvent::new(
EpollFlags::EPOLLOUT | EpollFlags::EPOLLET,
cur_socket as u64,
);
match epoll_ctl(epfd, EpollOp::EpollCtlMod, cur_socket, &mut ev) {
Ok(e) => {}
Err(err) => println!("Read ctl Err {:?}", err),
}
client.state = State::Write;
}
if cur_event == cur_event & EpollFlags::EPOLLOUT {
let buf = "HTTP/1.1 200 Ok\nConnection: close\nContent-Type: text/plain\n\nha?\n\n";
let buf_len = buf.len();
let mut sended = 0;
let mut need_to_close = false;
loop {
match write(cur_socket, &buf.as_bytes()[sended..]) {
Ok(len) => {
sended += len;
if sended >= buf_len {
need_to_close = true;
break;
}
}
Err(e) => {
need_to_close = true;
break;
}
}
}
if (need_to_close) {
match epoll_ctl(
epfd,
EpollOp::EpollCtlDel,
cur_socket as i32,
&mut epoll_events[i],
) {
Ok(e) => {}
Err(err) => println!("Err epollctl write {:?}", err),
}
clients.remove(&cur_socket);
match shutdown(cur_socket as i32, Shutdown::Both) {
Ok(e) => {}
Err(err) => println!("Err shutdown {:?}", err),
}
close(cur_socket as i32)?;
closed += 1;
println!("closed: {:?}", closed);
}
}
continue;
}
}
}
fn main() {
let server_sock = match socket(
AddressFamily::Inet,
SockType::Stream,
SockFlag::SOCK_NONBLOCK,
SockProtocol::Tcp,
) {
Ok(sock) => sock,
Err(err) => panic!("{:?}", err),
};
match setsockopt(server_sock, ReuseAddr, &true) {
Ok(_) => {}
Err(err) => panic!("Error set sock opt {:?}", err),
}
let addr = SockAddr::new_inet(InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 5468));
match bind(server_sock, &addr) {
Ok(_) => {}
Err(err) => panic!("Error bind: {:?}", err),
}
socket_to_nonblock(server_sock);
match listen(server_sock, 1024) {
Ok(_) => {}
Err(err) => panic!("Error listen: {:?}", err),
}
epoll_loop(server_sock.clone());
}
let listener = TcpListener::bind("localhost:1234").unwrap();
for stream in listener.incoming() {
let s = stream.unwrap();
handle_stream(s);
}
fn handle_stream(mut stream: TcpStream) -> () {
let mut buf = [0];
loop {
let _ = match stream.read(&mut buf) {
Err(e) => panic!("Got an error: {}", e),
Ok(m) => {
println!("Received {:?}, {:?}", m, buf);
if m == 0 {
// doesn't reach here.
break;
}
m
},
};
}
}
I then connect to the server by running curl http://localhost:1234.
I expect Ok(0) would be returned, but it doesn't reach that statement and it hangs instead. If that's an EOF, how can I treat in this case?
You want to use TcpStream::set_read_timeout and then check for that specific type of error:
use std::io::{self, Read};
use std::net::{TcpListener, TcpStream};
use std::time::Duration;
fn main() {
let listener = TcpListener::bind("localhost:1234").unwrap();
for stream in listener.incoming() {
let s = stream.unwrap();
handle_stream(s);
}
fn handle_stream(mut stream: TcpStream) -> () {
let mut buf = [0];
stream.set_read_timeout(Some(Duration::from_millis(100))).unwrap();
loop {
let _ = match stream.read(&mut buf) {
Err(e) => {
match e.kind() {
io::ErrorKind::WouldBlock => {
println!("would have blocked");
break;
},
_ => panic!("Got an error: {}", e),
}
},
Ok(m) => {
println!("Received {:?}, {:?}", m, buf);
if m == 0 {
// doesn't reach here.
break;
}
m
},
};
}
}
}