Crate tcp_handler

source ·
Expand description

§Tcp-Handler

Crate GitHub last commit GitHub issues GitHub pull requests GitHub

Read this in other languages: English, 简体中文.

§Description

More conveniently use tokio::net::TcpStream to transfer bytes::Bytes data chunks.

See tcp-server and tcp-client for conveniently building your tcp application.

§Features

  • Based on tokio and bytes.
  • Support ReadHalf and WriteHalf of tokio::net::TcpStream.
  • Support bytes::Buf. So you can send discontinuous data chunks by calling chain.
  • Support encryption (rsa and aes).
  • Support compression (flate2).
  • Complete API document and data model.

§Usage

Add this to your Cargo.toml:

[dependencies]
tcp-handler = "~0.5"

§Note

If client_init using encryption mode is extremely slow in debug mode, please add this to your Cargo.toml in client side:

[profile.dev.package.num-bigint-dig]
opt-level = 3 # Speed up rsa key gen.

This is an issue in rsa crate.

§Example

Directly transfer data. Without encryption and compression:

use anyhow::Result;
use bytes::{Buf, BufMut, BytesMut};
use tcp_handler::raw::{client_init, client_start, recv, send, server_init, server_start};
use tokio::net::{TcpListener, TcpStream};
use variable_len_reader::{VariableReader, VariableWriter};

#[tokio::main]
async fn main() -> Result<()> {
    // Create tcp stream.
    let server = TcpListener::bind("localhost:0").await?;
    let mut client = TcpStream::connect(server.local_addr()?).await?;
    let (mut server, _) = server.accept().await?;
    
    // Prepare the protocol of tcp-handler.
    let client_init = client_init(&mut client, &"test", &"0.0.0").await;
    let server_init = server_init(&mut server, &"test", |v| v == "0.0.0").await;
    server_start(&mut server, server_init).await?;
    client_start(&mut client, client_init).await?;
    
    // Send.
    let mut writer = BytesMut::new().writer();
    writer.write_string("hello server.")?;
    send(&mut client, &mut writer.into_inner()).await?;
    
    // Receive.
    let mut reader = recv(&mut server).await?.reader();
    let message = reader.read_string()?;
    assert_eq!("hello server.", message);
    
    Ok(())
}

Transfer message with encrypted protocol:

use anyhow::Result;
use bytes::{Buf, BufMut, BytesMut};
use tcp_handler::encrypt::{client_init, client_start, recv, send, server_init, server_start};
use tokio::net::{TcpListener, TcpStream};
use variable_len_reader::{VariableReader, VariableWriter};

#[tokio::main]
async fn main() -> Result<()> {
    // Create tcp stream.
    let server = TcpListener::bind("localhost:0").await?;
    let mut client = TcpStream::connect(server.local_addr()?).await?;
    let (mut server, _) = server.accept().await?;
    
    // Prepare the protocol of tcp-handler and the ciphers.
    let client_init = client_init(&mut client, &"test", &"0.0.0").await;
    let server_init = server_init(&mut server, &"test", |v| v == "0.0.0").await;
    let server_cipher = server_start(&mut server, server_init).await?;
    let client_cipher = client_start(&mut client, client_init).await?;
    
    // Send.
    let mut writer = BytesMut::new().writer();
    writer.write_string("hello server.")?;
    let client_cipher = send(&mut client, &mut writer.into_inner(), client_cipher).await?;
    
    // Receive.
    let (reader, server_cipher) = recv(&mut server, server_cipher).await?;
    let message = reader.reader().read_string()?;
    assert_eq!("hello server.", message);
    
    // Send.
    let mut writer = BytesMut::new().writer();
    writer.write_string("hello client.")?;
    let _server_cipher = send(&mut client, &mut writer.into_inner(), server_cipher).await?;
    
    // Receive.
    let (reader, _client_cipher) = recv(&mut server, client_cipher).await?;
    let message = reader.reader().read_string()?;
    assert_eq!("hello client.", message);
    
    Ok(())
}

The transmission method for compressed messages is similar to the above two, please use methods in compress and compress_encrypt mod.

Send discontinuous data chunks:

use anyhow::Result;
use bytes::{Buf, Bytes};
use tcp_handler::raw::{client_init, client_start, recv, send, server_init, server_start};
use tokio::net::{TcpListener, TcpStream};

#[tokio::main]
async fn main() -> Result<()> {
    // Connect
    let server = TcpListener::bind("localhost:0").await?;
    let mut client = TcpStream::connect(server.local_addr()?).await?;
    let (mut server, _) = server.accept().await?;
    let client_init = client_init(&mut client, &"chain", &"0").await;
    let server_init = server_init(&mut server, &"chain", |v| v == "0").await;
    server_start(&mut server, server_init).await?;
    client_start(&mut client, client_init).await?;

    // Using chain
    let mut messages = Bytes::from("a").chain(Bytes::from("b")).chain(Bytes::from("c"));
    send(&mut client, &mut messages).await?;
    let message = recv(&mut server).await?;
    assert_eq!(b"abc", message.as_ref());
    Ok(())
}

Re-exports§

Modules§

  • Common utilities for this crate.
  • compresscompression
    Compression protocol. Without encryption.
  • compress_encryptcompression and encrypt
    Compression and encryption protocol.
  • Global configuration for this crate.
  • encryptencrypt
    Encryption protocol. Without compression.
  • Raw protocol. Without encryption and compression.