use super::LinkTrait;
use core::fmt;
use std::io;
use std::net::{IpAddr, SocketAddr};
use std::sync::Arc;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
pub struct TcpClient {
addr: SocketAddr,
socket: TcpStream,
data: [u8; 4096],
}
impl TcpClient {
pub async fn new(addr: &str, port: u32) -> io::Result<TcpClient> {
let addr: IpAddr = addr.parse().unwrap();
let addr: SocketAddr = (addr, port as u16).into();
let socket = TcpStream::connect(&addr).await?;
Ok(TcpClient {
addr,
socket,
data: [0; 4096],
})
}
}
#[async_trait::async_trait]
impl LinkTrait for TcpClient {
async fn send(&mut self, msg: &[u8]) -> io::Result<()> {
self.socket.write_all(msg).await
}
async fn recv(&mut self) -> io::Result<Arc<Vec<u8>>> {
let len = self.socket.read(&mut self.data).await?;
let data = Arc::new(Vec::from(&self.data[..len]));
log::info!("{} recv: {:02X?}", self, data);
Ok(data)
}
}
impl From<TcpStream> for TcpClient {
fn from(socket: TcpStream) -> Self {
Self {
addr: socket.peer_addr().unwrap(),
socket,
data: [0; 4096],
}
}
}
impl fmt::Display for TcpClient {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_fmt(format_args!("TcpClient({:?})", self.addr))
}
}