I am trying to read data from the a device on one TCP port, format it, and then send the new data to a printer on another TCP port. I have lifted the sample code from the tokio docs. The TCP listener works as expected but I cannot get the peer connection working. If I use the samples individually in a main() function they work correctly. But when I combine them I am getting a method not found error with the write_all function in start_pos_listener(). I see that it is coming back with a Result but I have not been able to resolve it with a match statement. I understand that printer_socker.write_all is being called from tokio::spawn() which has no return type so I cannot pass the error up with ?. Any help would be appreciated. Thanks and Happy New Year to all.
main.rs
use std::error::Error;
use label_printer::Config;
use std::env;
use std::process;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let args: Vec<String> = env::args().collect();
let config = Config::new(&args).unwrap_or_else(|err| {
println!("Problem parsing arguments: {}", err);
process::exit(1);
});
match label_printer::start_pos_listener(config.pos, config.printer).await {
Ok(x) => x,
Err(_) => println!("Listener failure"),
};
Ok(())
lib.rs
use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpSocket;
use std::error::Error;
//use std::io;
pub struct Config {
pub pos: String,
pub printer: String,
}
impl Config {
pub fn new(args: &[String]) -> Result<Config, &'static str> {
if args.len() == 1 { //TODO: replace defaults with registry entries
let pos_ip = "192.168.0.49".to_string();
let pos_port = "9101".to_string();
let printer_ip = "192.168.0.62".to_string();
let printer_port = "9100".to_string();
let mut pos = String::new();
pos = pos + &pos_ip.trim() + ":" + &pos_port.trim();
let mut printer = String::new();
printer = printer + &printer_ip.trim() + ":" + &printer_port.trim();
Ok(Config {pos, printer})
} else {
if args.len() >= 4 {
let pos_ip = args[1].clone();
let pos_port = args[2].clone();
let printer_ip = args[3].clone();
let printer_port = args[4].clone();
let mut pos = String::new();
pos = pos + &pos_ip.trim() + ":" + &pos_port.trim();
let mut printer = String::new();
printer = printer + &printer_ip.trim() + ":" + &printer_port.trim();
Ok(Config {pos, printer})
} else {
Err("not enough arguments")
}
}
}
}
pub async fn start_pos_listener(pos: String, printer: String) -> Result<(), Box<dyn Error>> {
let listener = TcpListener::bind(pos).await?;
loop {
let (mut socket, _) = listener.accept().await?;
tokio::spawn(async move {
let mut buf = [0; 8192];
// In a loop, read data from the socket and write the data back.
loop {
let n = match socket.read(&mut buf).await {
// socket closed
Ok(n) if n == 0 => return,
Ok(n) => n,
Err(e) => {
println!("failed to read from socket; err = {:?}", e);
return;
}
};
let printer = "192.168.0.62:9100";
let addr = printer.parse().unwrap();
println!("{}", addr);
let printer_socket = TcpSocket::new_v4();
// Write the data back
let e = match printer_socket.write_all(&buf[0..n]).unwrap().await {
Err(it) => it,
_ => continue,
};
println!("failed to write to socket; err = {:?}", e);
return;
}
});
}
}