Comments (4)
Because pretty much everything is uses &mut self
you can just use Arc<Mutex<Context>>
, i would recommend the tokio Mutex.
Internal state is mutated when making any networking request, reading from a std::net::TcpStream
also requires it to be mutable for instance. It is generally not possible to make concurrent/parallel requests over the same connection.
For concurrent writes to the same server you would need two contexts but many devices can't handle parallel requests correctly.
Hope that helps.
from tokio-modbus.
I also believe there is an issue with sync::tcp::connect not closing the socket correctly.
I have the following code that eventually fails with too many open files error.
I have tested this with modbus-rs and it works.
extern crate chrono;
extern crate crossbeam_channel;
use std::sync::{Arc, Mutex};
use tokio_core::reactor::Core;
use futures::Future;
use tokio_modbus::prelude::*;
use systemd::daemon;
use chrono::{DateTime, NaiveDate, TimeZone, Utc};
use std::thread;
#[derive(Clone, Debug)]
struct MeterResult {
name: String,
ip: String,
result: Option<u32>,
last_dt: Option<DateTime<Utc>>
}
type MeterValue = (MeterResult, u32);
const NUMBER_OF_THREADS: usize = 10;
const NUMBER_OF_METERS: usize = 1000;
pub fn main() {
let mut meters: Vec<MeterResult> = vec![];
for i in 1..NUMBER_OF_METERS {
let meter: MeterResult = MeterResult {name: format!("bi{}", i),
ip: "127.0.0.1:5502".to_string(),
result: None,
last_dt: None
};
meters.push(meter);
}
let mut values = Arc::new(Mutex::new(vec![]));
let mut chunks = meters.chunks(NUMBER_OF_THREADS);
for chunk in chunks {
let mut threads = vec![];
for meter in chunk {
threads.push(thread::spawn( {
let clone = Arc::clone(&values);
let m = meter.clone();
move || {
let socket_addr = "127.0.0.1:5502".parse().unwrap();
let mut ctx = sync::tcp::connect(socket_addr).unwrap();
//let data = ctx.read_holding_registers(0x16, 2).unwrap();
//let value : u32 = ((data[1] as u32) << 16) | (data[0] as u32);
let mut v = clone.lock().unwrap();
v.push((m.clone(), 2));
//ctx.disconnect();
// drop(ctx);
// drop(socket_addr);
}
}));
}
for t in threads {
t.join().unwrap();
}
println!("batch done");
}
}
from tokio-modbus.
For everyone encountering this issue:
I once experienced a similar problem with the sync client. If you use tokio driven libraries you are actually best off to use them with async/await. One solution for the first question of this issue, is to use tokio::spawn to spawn tasks and at the end join them using the futures crate. This solution lets tokio decide how many threads to use and to concurrently run multiple tasks on one thread if for instance one of the slaves takes long to respond to the request.
from tokio-modbus.
I can't figure out how to make async
requests via one Context
. The problem is read_*
requests expect mutable reference to Context
. I'd like to write something like that:
let mut context = tokio_modbus::client::tcp::connect("127.0.0.1:502".parse()?).await?;
let (a, b) = tokio::join!(
context.read_holding_registers(1, 1),
context.read_holding_registers(2, 1),
);
context.disconnect().await?;
dbg!(a, b);
I've tried to create a context for every request but a server doesn't like this. I thought about to wrap context in Arc<RwLock>
but I think it's a not good idea.
from tokio-modbus.
Related Issues (20)
- Flow control when using RS-485 HOT 2
- No timeout in the RTU client async implementation HOT 2
- Infinite retry loop with heavy CPU load HOT 5
- "Device or resource busy" in RTU server example HOT 3
- Generalize impl around `Service` usage HOT 5
- Tokio module 'runtime' is private HOT 12
- Asyncronous responses / Multiplexing HOT 2
- How to convert tokio_modbus::Request to bytes? HOT 5
- TCP server example - shared data hashmap HOT 5
- TCP Sync Client HOT 6
- write_multiple_registers taking array as a param HOT 3
- Can not disconnect slave, need help HOT 3
- Although disconnect the context, the SerialStream reopen error HOT 1
- Patterns/best practice for reconnect-after-failure? HOT 1
- How to turn 'tokio_serial::SerialStream' into global static to save it for reuse
- is_connected()? HOT 1
- Modbus RTU - Serial Direction Pin HOT 6
- Dev Dependencies: Upgrade rustls-pemfile and tokio-rustls HOT 4
- Return Modbus exception codes for client and server.
- Use `async-trait` in `Service` trait ? HOT 10
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tokio-modbus.