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 new to rust and struggling with an issue. I'm looking to read output from serial and convert it to JSON.
Below is the section of code that reads in the serial output.
match serialport::open(&port_name) {
Ok(mut port) => {
let mut serial_buf: Vec<u8> = vec![0; 1000];
loop {
match port.read(serial_buf.as_mut_slice()) {
Ok(t) => handle_event(&serial_buf[..t]),
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => (),
Err(e) => print!("Port read error: {}\n", e),
};
}
}
Err(e) => {
println!("Failed to open \"{}\". Error: {}", port_name, e);
::std::process::exit(1);
}
};
Next that output is passed to serde to be parsed. However the output it gets isn't always the complete JSON string so serde breaks. I believe I need to buffer the response here but struggling to fit that in.
fn handle_event(buf: &[u8]) {
let e_str = match str::from_utf8(buf) {
Ok(v) => v,
Err(e) => { print!("Str conversion error: {}\n", e); return; },
};
let e = match serde_json::from_str::<Event>(e_str) {
Ok(e) => e,
Err(e) => { print!("JSON parse error: {}\n", e); return; },
};
print!("{}", e.name);
}
Thanks in advance for any help.
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
},
};
}
}
}