#tcp #websocket #sockets #callback #ws #server-client #read-write

cbsk_socket

cbsk_socket is a socket callback tool

23 releases (2 stable)

new 1.0.1 Apr 24, 2024
0.6.3 Apr 11, 2024
0.5.2 Apr 7, 2024
0.4.0 Mar 29, 2024
0.2.2 Dec 29, 2023

#272 in Asynchronous

Download history 16/week @ 2023-12-27 11/week @ 2024-01-03 22/week @ 2024-01-10 120/week @ 2024-02-14 262/week @ 2024-02-21 251/week @ 2024-02-28 14/week @ 2024-03-06 463/week @ 2024-03-13 452/week @ 2024-03-20 549/week @ 2024-03-27 337/week @ 2024-04-03 475/week @ 2024-04-10

1,841 downloads per month
Used in 2 crates

MIT/Apache

125KB
2K SLoC

cbsk_socket is a socket callback tool
you can use cbsk_socket create TCP/WebSocket server or client, you don't need to focus on TCP/WebSocket read and write, just focus on business processing

minimum supported Rust version

Rust 1.75.0

now supported sockets

  • tcp client √
  • tcp server √
  • ws client √
  • ws server √

tcp server example

tcp server example

Cargo.toml file:

fast_log = "1.6.16"
cbsk_base = { version = "0.1.8" }
cbsk_socket = { version = "1.0.1", features = ["tcp_server"] }

main.rs file:

use std::net::{IpAddr, SocketAddr};
use std::sync::Arc;
use cbsk_base::{log, tokio};
use cbsk_socket::tcp::server::callback::TcpServerCallBack;
use cbsk_socket::tcp::server::client::TcpServerClient;
use cbsk_socket::tcp::server::config::TcpServerConfig;
use cbsk_socket::tcp::server::TcpServer;
use cbsk_socket::tcp::write_trait::WriteTrait;

#[tokio::main]
async fn main() {
    // print log to console
    let fast_config = fast_log::config::Config::default().console();
    fast_log::init(fast_config).unwrap();

    // start tcp server
    let addr = SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 8080);
    let tcp_config = TcpServerConfig::new("test".into(), addr, false);
    let tcp_server = TcpServer::new(tcp_config.into(), TcpServerBusiness {}.into());
    let handle = tcp_server.start::<1024>();

    // wait handle
    handle.await.unwrap();

    // wait log flush
    log::logger().flush();
}

/// you tcp server business
pub struct TcpServerBusiness {}

/// business callback
impl TcpServerCallBack for TcpServerBusiness {
    async fn recv(&self, bytes: Vec<u8>, client: Arc<TcpServerClient>) -> Vec<u8> {
        println!("{} read bytes [{bytes:?}]", client.log_head);

        // send bytes to tcp client
        client.send_bytes(b"hello world").await;
        client.send_text("hello world").await;
        client.send_json(&"hello world".to_string()).await;

        Vec::new()
    }
}

tcp client example

tcp client example

Cargo.toml file:

fast_log = "1.6.16"
cbsk_base = { version = "0.1.8", features = ["async-trait"] }
cbsk_socket = { version = "1.0.1", features = ["tcp_client"] }

main.rs file:

use std::net::{IpAddr, SocketAddr};
use std::time::Duration;
use cbsk_base::async_trait::async_trait;
use cbsk_base::{log, tokio};
use cbsk_socket::config::re_conn::SocketReConn;
use cbsk_socket::tcp::client::callback::TcpClientCallBack;
use cbsk_socket::tcp::client::config::TcpClientConfig;
use cbsk_socket::tcp::client::TcpClient;
use cbsk_socket::tcp::write_trait::WriteTrait;

#[tokio::main]
async fn main() {
    // print log to console
    let fast_config = fast_log::config::Config::default().console();
    fast_log::init(fast_config).unwrap();

    // start tcp client
    let addr = SocketAddr::new(IpAddr::from([127, 0, 0, 1]), 8080);
    let tcp_config = TcpClientConfig::new("test".into(), addr, SocketReConn::enable(Duration::from_secs(3)));
    let tcp_client = TcpClient::new(tcp_config.into(), TcpClientBusiness {}.into());
    let read_handle = tcp_client.start::<1024>();

    // if tcp server connect success, send bytes to tcp server
    let write_handle = tokio::spawn(async move {
        loop {
            if tcp_client.is_connected() {
                tcp_client.send_bytes(b"hello world").await;
                tcp_client.send_text("hello world").await;
                tcp_client.send_json(&"hello world".to_string()).await;
            }

            tokio::time::sleep(Duration::from_secs(3)).await;
        }
    });

    // wait handle
    read_handle.await.unwrap();
    write_handle.await.unwrap();

    // wait log flush
    log::logger().flush();
}

/// you tcp client business
pub struct TcpClientBusiness {}

/// business callback
#[async_trait]
impl TcpClientCallBack for TcpClientBusiness {
    async fn recv(&self, bytes: Vec<u8>) -> Vec<u8> {
        println!("read bytes [{bytes:?}]");

        Vec::new()
    }
}

features explain

the following features are only valid for tcp_server or tcp_client

  1. default is tokio_tcp, use tokio runtime and tokio tcp
  2. tokio_tcp, use tokio runtime and tokio tcp
  3. system_tcp, use tokio runtime and system tcp

other issues

  1. The reason for adding system tcp and thread runtime is that during some Linux testing, there was a deadlock issue with tokio::net::TcpStream + tokio runtime, causing tokio to not run. As this Linux is customized, we are currently unable to provide testable issues to Tokio. If you are using Windows, Windows Server 2012, macos, ubuntu, etc., this cargo crate is normal and you can use the default tokio_tcp

  2. websocket tls coming soon
    if y want to use tls, y can use tokio-tungstenite(github)

Dependencies

~1–12MB
~101K SLoC