tokio

async是什么

async 是 Rust 选择的异步编程模型

block_on()----执行器

async fn do_something(){
    println!("go,go,go");
}
fn main() {
   do_something();
}

use futures::executor::block_on;
async fn do_something(){
    println!("go,go,go");
}
fn main() {
    let future=do_something();
    block_on(future);
}

状态机

调用非执行

async标记的函数(代码)是一个状态机,当调用这个函数时,并不是执行者函数,只是返回这个状态机的futures特征

执行futures

block_on()------.await

block_on()--->阻塞

.await--->并发

async fn函数中使用.await可以等待另一个异步调用的完成。但是与block_on不同,.await并不会阻塞当前的线程,而是异步的等待Future A的完成,在等待的过程中,该线程还可以继续执行其它的Future B,最终实现了并发处理的效果。

.await的作用

.await不会发起像block_on()一样让线程阻塞的操作,但是也不是说,可以让.await之后的代码可以.await一起运行,而是也要等到.await这一行代码运行完,之后的代码才能运行。

use std::time::Duration;
use std::thread::sleep;
use futures::executor::block_on;

async fn do_first(){
    sleep(Duration::from_secs(10));
    println!("do_first");
}
async fn do_second(){
    println!("do_second");
}
async fn goto_do(){
    do_first().await;
    do_second().await;
}
fn main(){
    let m_future=goto_do();
    block_on(m_future);
}

 

.await的使用需要先引入一下包:

[dependencies]
futures = "0.3"
 

代码块什么时候返回

block_on执行future之后才会返回函数的返回值

block_on嵌套block_on不行:

use futures::executor::block_on;
async fn do_something(){
    //do_another().await;//异步执行
    let future=do_another();
    block_on(future);
    println!("go,go,go");
}
async fn do_another(){
    println!("do,do,do");
}
fn main() {
    let future=do_something();
    block_on(future);//阻塞当前线程
}

代码奔溃

因为这里只有一个线程,想要两次阻塞是不可能的。

awiat作用范围

只允许在async标识的函数或者代码块内部使用。

Future 需要被执行器poll(轮询)后才能运行,

Future 并不能保证在一次 poll 中就被执行完, 

当未来 Future 准备好进一步执行时, 该函数会被调用去通知执行器,这个Future准备好了,

(这个同C++的epoll,通过回调,而非轮询的方式)

(考虑一个需要从 socket 读取数据的场景:如果有数据,可以直接读取数据并返回 Poll::Ready(data), 但如果没有数据,Future 会被阻塞且不会再继续执行,此时它会注册一个 wake 函数,当 socket 数据准备好时,该函数将被调用以通知执行器:我们的 Future 已经准备好了,可以继续执行。)

最外层的 async 函数,执行器 executor推动它们运行,

几个重要的概念

async

async 是 Rust 选择的异步编程模型;

异步编程使用async fn 语法来创建一个异步函数;

有两种方式可以使用async: async fn用于声明函数,async { ... }用于声明语句块,它们会返回一个实现 Future 特征的值;

.await

Future

Future是一个特征,返回的Future是返回实现了这个Future的特征的实例对象。

future运行的方法

async 是懒惰的,直到被执行器 poll 或者 .await 后才会开始运行,其中后者是最常用的运行 Future 的方法。 

waker的wake函数

Future 将从 Socket 读取数据,若当前还没有数据,则会让出当前线程的所有权,允许执行器去执行其它的 Future 。当数据准备好后,会调用 wake() 函数将该 Future 的任务放入任务通道中,等待执行器的 poll 。

执行器

pin和Unpin

问题:本来指向的地址的值被移动了

Tokio服务编程

模块

use tokio::net::{TcpListener, TcpStream};

#[tokio::main]宏

对于main函数,tokio提供了简化的异步运行时创建方式:

main函数默认不可以async fn修饰为异步函数,但是可以用#[tokio::main]宏代替fm main.

网络编程步骤

1,引入tokio模块

在正式开始学习tokio之前,当然是在Cargo.toml中引入tokio。在Cargo.toml文件中添加以下依赖:

// 开启全部功能的tokio, // 在了解tokio之后,只开启需要的特性,减少编译时间,减小编译大小 tokio = {version = "1.4", features = ["full"]}

创建连接的方法

2-1:最简单的---->绑定,接收就完成

server端---绑定并接收

TcpListener代表服务端套接字,可使用bind()方法指定要绑定的地址,bind()之后再await,即可开始监听。

async fn main(){
    let listener = TcpListener::bind("127.0.0.1:8888").await.unwrap();

    loop {
        let (socktfd, client_sock_addr) = listener.accept().await.unwrap();
        tokio::spawn(async move {
          // 该任务负责处理client
        });
    }
}

这里的listener代表的是服务端负责监听的套接字。

client端----connect

use tokio::net::TcpStream;
#![allow(unused)]
fn main() {
let mut socketfd = TcpStream::connect("127.0.0.1:8080").await.unwrap();
}

以上,无论是服务端还是客户端的socketfd,套接字的类型都是TcpStream

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值